C# Enums Tutorial

1- What is C# Enum

enum trong C# là một từ khóa, nó sử dụng để khai báo một tập hợp đặc biệt.
Giờ chúng ta cần xem nếu không có Enum trong một số tình huống bạn phải làm thế nào, chẳng hạn bạn cần một tập hợp chứa các ngày trong tuần. Thông thường bạn định nghĩa ra 7 hằng số tự nhiên để đại diện cho 7 trong tuần.
WeekDayConstants.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
    class WeekDayConstants
    {
         public const int MONDAY = 2;
         public const int TUESDAY = 3;
         public const int WEDNESDAY = 4;
         public const int THURSDAY = 5;

         public const int FRIDAY = 6;
         public const int SATURDAY = 7;
         public const int SUNDAY = 1;
    }

}
A class with a method returns the job todo in each specific day of week. (Kind of a timetable).
Timetable.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
    
    class Timetable
    {
        // Returns name of Job will do
        public static String getJob(int dayInWeek)
        {
            if (dayInWeek == WeekDayConstants.SATURDAY
                    || dayInWeek == WeekDayConstants.SUNDAY)
            {
                return "Nothing";
            }
            return "Coding";
        }
    }

}
It is obvious that such code lines are not safe. For example, you call Timetable.getJob(int) function, but the input parameter does not belong to a defined set.
  1. No Type-Safety: First of all it’s not type-safe; you can assign any valid int value to dayInWeek
  2. No Meaningful Printing: printing value of any of these constant will print its numeric value instead of meaningful name of day e.g. when you print MONDAY it will print "2" instead of "MONDAY"
 
Và đây là cách sử dụng Enum để định nghĩa ra các ngày trong tuần.
WeekDay.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
    public enum WeekDay
    {
       MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }

}
And examplesusing Weekday enum:
Timetable2.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
    class Timetable2
    {
        public static String getJob(WeekDay weekDay)
        {
            if (weekDay == WeekDay.SATURDAY || weekDay == WeekDay.SUNDAY)
            {
                return "Nothing";
            }
            return "Coding";
        }
    }

}

2- Can use the == operator to compare the elements of enum

Enum is a reference object like a class, interface, but it can also use the == operation
Let see how reference objects are compared.

// To compare the reference object, generally used method equals(..)
object obj1 = ...;

// Comparing object with null, can use the == operator
if (obj1 == null)
{

}

object obj2 = ...;
// Not null
if (obj1 != null)
{
    // Comparing two objects.
    if (obj1.Equals(obj2))
    {

    }
}
With Enum, you can use the == operator to compare.
CompareEnumDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
   class CompareEnumDemo
   {
       public static void Main(string[] args)
       {

           WeekDay today = WeekDay.SUNDAY;

           // Use the == operator to compare two elements of Enum
           if (today == WeekDay.SUNDAY)
           {
               Console.WriteLine("Today is Sunday");
           }
           Console.Read();
       }
   }

}

3- Fetch on the elements of Enum

We can fetch on all elements of Enum. See examples:
ValuesDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
    class ValuesDemo
    {
        public static void Main(string[] args)
        {
            

            // Get all the elements of the Enum.
            Array allDays = Enum.GetValues(typeof(WeekDay));

            foreach (WeekDay day in allDays)
            {
                Console.WriteLine("Day: " + day);
            }


            Console.Read();
        }       
           
    }

}
Results of running the example:

4- Enum with Attribute

See more about C # Attribute:
  • TODO
GenderAttr.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
    class GenderAttr : Attribute
    {
        // code: M, text = Male
        // code: F, text = Female
        internal GenderAttr(string code, string text)
        {
            this.Code = code;
            this.Text = text;
        }

        public string Code { get; private set; }

        public string Text { get; private set; }  
             
    }

}
Gender Enum has two elements MALE and FEMALE.
Gender.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
    public enum Gender
    {
        // A element of Enum, has attribute
        [GenderAttr("M","Male")]
        MALE,

        // A element of Enum, has attribute
        [GenderAttr("F","Female")]
        FEMALE

    }

 
}
Genders.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace CSharpEnumTutorial
{
    class Genders
    {
        // Returns Gender corresponding to the code.
        // (This method may returns null)
        public static Gender? GetGenderByCode(string code)
        {
            // Get all the elements of the Enum.
            Array allGenders = Enum.GetValues(typeof(Gender));

            foreach (Gender gender in allGenders)
            {
                string c = GetCode(gender);
                if (c == code)
                {
                    return gender;
                }
            }
            return null;
        }

        public static string GetText(Gender gender)
        {
            GenderAttr genderAttr = GetAttr(gender);
            return genderAttr.Text;
        }

        public static string GetCode(Gender gender)
        {
            GenderAttr genderAttr = GetAttr(gender);
            return genderAttr.Code;
        }

        private static GenderAttr GetAttr(Gender gender)
        {
            MemberInfo memberInfo = GetMemberInfo(gender);
            return (GenderAttr)Attribute.GetCustomAttribute(memberInfo, typeof(GenderAttr));
        }

        private static MemberInfo GetMemberInfo(Gender gender)
        {
            MemberInfo memberInfo
                = typeof(Gender).GetField(Enum.GetName(typeof(Gender), gender));

            return memberInfo;
        }
    }

}
And example using Gender enum:
GenderTest.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpEnumTutorial
{
   class GenderTest
   {
       public static void Main(string[] args)
       {

           Gender marryGender = Gender.FEMALE;

           Console.WriteLine("marryGender: " + marryGender);

           Console.WriteLine("Code: " + Genders.GetCode(marryGender)); // F
           Console.WriteLine("Text: " + Genders.GetText(marryGender)); // Femate


           
           String code = "M";
           Console.WriteLine("Code: " + code);

 
           // Phương thức có thể trả về null.
           Gender? gender = Genders.GetGenderByCode(code);

           Console.WriteLine("Gender by code: " + gender);

           Console.Read();
       }
   }

}
Running the example: