نوع دادهی enum و کاربرد آن در یونیتی
نوع دادهی enum (که کوتاهشدهی عبارت Enumeration Type است و اینام خوانده میشود) در سادهترین تعریف خود جواب پرسشی است که پاسخ آن تنها میتواند یکی از گزینههای محدودی باشد که از قبل برای آن پرسش تعریف شده است. پس از تعریف یک enum، میتوان از روی آن متغیرهایی تعریف کرد که میتوانند یکی از گزینههای پاسخ را به عنوان مقدار در خود ذخیره کنند.
به عنوان مثال یک enum به نام Today را در نظر بگیرید که قصد داریم شمارهی روز امروز را در آن قرار دهیم. متغیر این enum که وظیفهی ذخیرهی یک روز از هفته را بر عهده دارد تنها میتواند یکی از مقادیر شنبه، یکشنبه، دوشنبه، سهشنبه، چهارشنبه، پنجشنبه یا جمعه را در خود ذخیره کند. بدیهی است که روز هفته تنها یکی از گزینههای محدود ذکر شده است و حالت دیگری وجود ندارد. در چنین مواردی از نوع دادهی enum استفاده میکنیم.
نمایشی بصری از مفهوم enum؛ این نوع داده بسیار پراستفاده و کاربردی است و به احتمال زیاد تا قبل از آشنایی با enum سروکار زیادی با این نوع داده در برنامههای مختلف داشتهایم. تصویر فوق یک متغیر enum است که در Inspector یونیتی سریالایز شده است.
نکته
نوع دادهی enum از نوع value type است.
تعریف یک enum جدید
برای تعریف یک enum جدید پس از نوشتن کلمهی کلیدی enum
و انتخاب یک نام برای آن، تمام گزینههای ممکن برای پاسخ را بین آکلاد نوشته و آنها را با ویرگول از هم جدا میکنیم. به عنوان مثال برای تعریف enum روزهای هفته چنین میکنیم:
نکته
در تعریف گزینههای یک enum از دابل کوتیشن ” در دو طرف آن استفاده نمیکنیم (همانند کاری که هنگام نوشتن یک string در کد انجام میدادیم). همچنین در هنگام تعریف enum از عملگر تخصیص (=) استفاده نمیشود و گذاشتن سمی کالن در آخر تعریف نیز اختیاری است.
طبق قراردادهای نامگذاری، نامگذاری enum باید به صورت PascalCase و به صورت مفرد باشد (مگر در enum های بیتی که از اسم جمع استفاده می شود).
بهتر است در صورتی که گزینه ها اولویت خاصی نسبت به یکدیگر ندارند به ترتیب حروف الفبا نوشته شوند. چرا که در هر صورت اعضای enum در IntelliSense به ترتیب حروف الفبا نمایش داده می شوند که ممکن است گاهی گیج کننده شود.
ایجاد متغیر از روی enum از قبل ساخته شده
در نهایت برای ایجاد متغیر از روی enum ساخته شده و مقداردهی آن از بین گزینههای پاسخ (مثلاً گزینهی Sunday
در این مثال) از چنین کدی استفاده میکنیم:
همانطور که مشاهده میکنید دسترسی به یک گزینه از بین گزینههای ممکن برای پاسخ یک enum با نوشتن نام enum و عملگر نقطه (dot operator) و سپس نوشتن نام گزینه امکانپذیر است.
کاربرد enum در یونیتی
این نوع داده در توسعهی بازی کاربردهای فراوانی دارد؛ از جمله استفاده از switch caseها و مواردی که هوش مصنوعی بازی باید از بین چندین الگوریتم یکی را انتخاب کند (مثل یک دشمن NPC که چندین روش حمله به بازیکن برای آن نوشته شده و بسته به شرایط موجود باید یکی از آنها را انتخاب کند).
همچنین فریمورک یونیتی نیز به کرات از این نوع داده استفاده کرده است. برای مثال اینام KeyCode
که اختصاصی یونیتی بوده و در آن تمام دکمههای صفحهکلید و کنترلر کنسولها لیست شده است و در هنگام کدنویسی برای صحبت از یک دکمهی خاص باید از این enum استفاده کرد:
جزئیات کار با نوع دادهی enum
cast کردن در متغیرهای ساخته شده از روی enumها
در یک enum تعریف شده، گزینههایی که برای آن در نظر گرفته میشود در واقع مجموعهای از ثوابت هستند. به هر گزینه به طور پیشفرض یک ثابت integer نظیر میشود که اولین گزینه نظیر به عدد 0، دومین گزینه نظیر به عدد 1 و تناظر به همین صورت ادامه دارد. با cast کردن نمونه به int میتوان این عدد را به دست آورد (همچنین برعکس این عمل یعنی cast کردن یک int به نوع enum نیز امکانپذیر است):
باید دقت شود که امکان cast کردن enum به string به دلیل قرار نداشتن آن ها در یک سلسله مراتب وراثت وجود ندارد و باید برای این کار از متد ToString (از کلاس Object) استفاده شود.
نکته
cast کردن بیشتر برای تغییر نوع اشارهگر به یک شی استفاده می شود و برای به دست آوردن عدد متناظر به نمونه (در صورتی که قرارگیری عدد در string اهمیتی نداشته باشد و برای مثال تنها قصد نمایش آن در Console را داشته باشید) بهتر است از روش جایگزین cast که در ادامه توضیح داده شده است استفاده شود.
استفاده از متد ToString کلاس Object بر روی متغیر ساخته شده از روی enum
استفاده از این متد بدون وارد کردن هرگونه آرگومان، باعث برگشت مقدار در قالب string میشود. اما با وارد کردن رشتهی "D"
در ورودی متد، میتوان نوع خروجی را به عدد Decimal که در یک string قرار گرفته است تغییر داد:
دقت کنید که هرچند مقدار نهایی todayValueToDecimal
عدد 0 است، اما این عدد در یک string قرار گرفته است و این تفاوت استفاده از cast و متد ToString
است.
cast کردن string به گزینهی enum
برای تبدیل string به گزینهی enum باید از کد زیر استفاده نمود که البته کمی پیچیدهتر است (این string باید از گزینههای موجود در enum باشد که در غیر این صورت با exception روبرو میشویم):
cast کردن عبارت نهایی به Day
به این دلیل است که خروجی متد Parse
کلاس Enum
همواره یک Object
است و برای قرارگیری در فیلد Tomorrow
باید به Day
تبدیل شود.
تغییر شمارههای ثوابت گزینههای enum از مقادیر پیشفرض به مقادیر دلخواه
همانطور که گفته شد شمارهگذاری اعضای enum به صورت پیشفرض از 0 شروع شده و به ترتیب به هر عضو عدد بعدی نظیر میشود. اما در این بین میتوان با گذاشتن علامت مساوی در کنار یک عضو و نوشتن یک شماره (یا یک const همنوع ثابت و یا حتی مقدار یکی دیگر از اعضا با نوشتن نام آن عضو)، این عدد پیشفرض را تغییر داد:
این نوع شمارهگذاری (دنبالهی هندسی با قدرنسبت 2) معمولاً در enumهای بیتی (که خصوصیت [Flags]
را دارا هستند) به کار میرود.
نکته
در صورتی که در جلوی یک عضو که به صورت دستی شمارهگذاری شده، عضو یا اعضای دیگری قرار داشته باشند که به صورت دستی شمارهگذاری نشده باشند، مقدار ثابت پیشفرض آنها از مقدار ثابت عضو قبلی (آخرین عضو دستی شمارهگذاری شده) شروع به شمارش میکند (با اضافه شدن یک واحد به مقدار در هر عضو). یعنی در کد بالا مقدار Friday
برابر با 17
و مقدار Saturday
برابر با 18
خواهد بود.
تغییر نوع ثوابت enumها از نوع پیشفرض (int) به سایر انواع
هرچند این قابلیت چندان کاربردی ندارد، اما میتوان دلایلی نادر مثل کمبود ظرفیت متغیر int را به میان آورد که در این حالت باید ثوابت enum در یک متغیر با محدودهی بیشتر قرار گیرند. انواع مجاز برای این کار عبارتند از:
byte, sbyte, short, ushort, int, uint, long, ulong
برای انجام این کار هنگام تعریف enum، پس از نوشتن نام موردنظر برای enum کاراکتر دونقطه (:
) و سپس نوع موردنظر نوشته میشود:
نکته
امکان استفاده از متدهای توسعهیافته برای نمونههای ساخته شدهی enum وجود ندارد، هرچند میتوان برای خود نوع Enum
از متدهای توسعهیافته استفاده کرد. چرا که تمامی enumها از کلاس Enum
ارثبری میکنند (طبق قرارداد سی شارپ enumها همگی sealed هستند و تنها از کلاس Enum
ارثبری میکنند). برخلاف نمونهها، خود کلاس Enum
از نوع reference type است.
استفاده از enum در حلقه
یکی از قابلیتهای جالب enum امکان استفاده از آن به عنوان iteration variable (متغیرهایی که در ساختارهای تکرار استفاده میشوند) است. به عنوان مثال داریم:
در این مثال با این که متغیر dayInTheLoop
عددی نیست، اما امکان استفاده از آن در حلقه وجود دارد.