نوع شمارشی (Enum)
یک نوع شمارشی یا enum، راهی برای تعریف مجموعهای از ثابتهای
نامگذاری شده است. این ثابتها معمولاً نمایانگر یک گروه از مقادیر مرتبط و محدود هستند. استفاده
از enum به جای اعداد صحیح یا رشتههای متنی، خوانایی کد را به شدت
افزایش داده و احتمال بروز خطا در اثر وارد کردن مقادیر نامعتبر را کاهش میدهد.
تعریف یک enum
برای تعریف یک نوع شمارشی از کلمهی کلیدی enum استفاده میکنیم. به
عنوان مثال، فرض کنید میخواهیم روزهای هفته را مدلسازی کنیم.
Program.cs
public enum DayOfWeek
{
Saturday,
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
}
در کد بالا، ما یک نوع جدید به نام DayOfWeek تعریف کردهایم. هر یک
از اعضای این enum (مانند Saturday،
Sunday و ...) یک ثابت نامگذاری شده است. به طور پیشفرض، نوع دادهی
پایه برای هر عضو، int است و مقادیر به ترتیب از صفر شروع میشوند.
یعنی Saturday برابر 0، Sunday برابر 1
و به همین ترتیب تا آخر.
استفاده از enumها
پس از تعریف enum، میتوانیم متغیری از آن نوع ایجاد کرده و یکی از
مقادیر تعریف شده را به آن اختصاص دهیم. این کار باعث میشود کد ما بسیار توصیفی و قابل فهم شود.
Program.cs
DayOfWeek today = DayOfWeek.Wednesday;
if (today == DayOfWeek.Friday)
{
Console.WriteLine("It's the weekend!");
}
else
{
Console.WriteLine("Back to work.");
}
switch (today)
{
case DayOfWeek.Thursday:
case DayOfWeek.Friday:
Console.WriteLine("Almost the weekend!");
break;
default:
Console.WriteLine("It's a weekday.");
break;
}
همانطور که میبینید، استفاده از DayOfWeek.Wednesday بسیار خواناتر
از استفاده از یک عدد بیمعنا مثل 4 است. هر کسی که کد را میخواند فوراً متوجه منظور
آن میشود. ساختار switch نیز با enum
ها بسیار خوب کار میکند و به شما اجازه میدهد منطقهای شرطی پیچیده را به شکلی تمیز پیادهسازی
کنید.
تغییر نوع پایه و مقادیر شمارش
شما میتوانید نوع دادهی پایهی یک enum را به هر نوع صحیح دیگری
(مانند byte, sbyte, short, ushort, long, ulong) تغییر دهید. این کار زمانی
مفید است که بخواهید در مصرف حافظه صرفهجویی کنید. همچنین میتوانید مقادیر عددی دلخواه خود را به
اعضای enum اختصاص دهید.
Program.cs
public enum UserRole : byte
{
Guest = 0,
Member = 10,
Moderator = 50,
Admin = 100
}
UserRole currentUserRole = UserRole.Admin;
int roleValue = (int)currentUserRole;
Console.WriteLine($"Role: {currentUserRole}, Value: {roleValue}");
در این مثال، نوع پایهی UserRole را به byte تغییر دادهایم که فضای کمتری نسبت به int اشغال میکند. همچنین مقادیر مشخصی را برای هر نقش کاربری تعیین
کردهایم. برای به دست آوردن مقدار عددی یک عضو enum، باید آن را به
نوع عددی مورد نظر تبدیل (cast) کنیم.
نوع ساختار (Struct)
ساختار یا struct یکی دیگر از انواع مقداری (Value Type) در
C# است که به شما اجازه میدهد چندین متغیر مرتبط را در یک واحد دادهای کپسوله کنید.
ساختارها برای دادههای کوچک و سبکی که رفتار مقداری دارند، ایدهآل هستند. بر خلاف کلاسها که نوع
ارجاعی (Reference Type) هستند، متغیرهای از نوع struct خود داده را
مستقیماً در خود نگه میدارند، نه یک ارجاع به داده در حافظه.
تعریف یک struct
برای تعریف یک ساختار، از کلمهی کلیدی struct استفاده میکنیم. یک
ساختار میتواند شامل فیلدها (متغیرها)، پراپرتیها و متدها باشد، دقیقاً مانند یک کلاس.
Program.cs
public struct Point
{
public double X;
public double Y;
public Point(double x, double y)
{
X = x;
Y = y;
}
public void Display()
{
Console.WriteLine($"({X}, {Y})");
}
}
در کد بالا، یک ساختار به نام Point تعریف کردهایم که برای نمایش یک
نقطه در فضای دو بعدی به کار میرود. این ساختار دو فیلد عمومی X و
Y، یک سازنده (constructor) برای مقداردهی اولیه فیلدها، و یک متد
برای نمایش مختصات دارد.
ایجاد و استفاده از structها
برای ایجاد یک نمونه از یک ساختار، معمولاً از کلمهی کلیدی new به
همراه سازندهی آن استفاده میکنیم. پس از ایجاد نمونه، میتوانیم به اعضای آن دسترسی پیدا کنیم.
Program.cs
Point p1 = new Point(10, 20);
Console.WriteLine("Initial coordinates:");
p1.Display();
p1.X = 50;
Console.WriteLine("New coordinates:");
p1.Display();
یک نکتهی مهم در مورد ساختارها این است که چون نوع مقداری هستند، وقتی یک متغیر struct را به متغیر دیگری اختصاص میدهید، یک کپی
کامل از داده ایجاد میشود. این رفتار با کلاسها که در آن فقط ارجاع کپی میشود، متفاوت است. این
موضوع را در درس بعدی به تفصیل بررسی خواهیم کرد.
چه زمانی از struct به جای class استفاده کنیم؟
انتخاب بین struct و class یک تصمیم
مهم در طراحی است. به طور کلی، از struct در شرایط زیر استفاده
کنید:
- نمایندگی یک مقدار واحد: زمانی که نوع دادهی شما به طور منطقی یک مقدار
واحد را نشان میدهد، مانند یک عدد مختلط، یک رنگ، یا یک نقطه.
- اندازه کوچک: زمانی که اندازه نمونههای نوع شما کوچک است (معمولاً کمتر
از 16 بایت).
- عدم تغییرپذیری (Immutability): ساختارها برای دادههایی که پس از ایجاد
تغییر نمیکنند، گزینهی بسیار خوبی هستند.
- عدم نیاز به وراثت: ساختارها از وراثت پشتیبانی نمیکنند (نمیتوانند از
کلاس یا ساختار دیگری ارثبری کنند).
در سایر موارد، به خصوص برای موجودیتهای پیچیدهتر که هویت و طول عمر مشخصی دارند (مانند Customer، Order یا Window)، استفاده از class انتخاب
صحیح است.