Friday, 5 February 2016

Enums in C#

Introduction

Let's study enums in C sharp. But before that let us first understand the necessity of using enums. Consider the following program.

P1.cs

class Demo
{
  public static void Main()
  {
      int Sunday = 0;
      System.Console.WriteLine(Sunday);
  }
}

Output

0
The above program compiles and runs successfully to give the desired output. Let's add other weekdays too.

P2.cs

class Demo
{
  public static void Main()
  {
      int Sunday = 0;
      int Monday = 1;
      int Tuesday = 2;
      int Wednesday = 3;
      int Thursday = 4;
      int Friday = 5;
      int Saturday = 6;
      System.Console.WriteLine(Sunday);
      System.Console.WriteLine(Monday);      
      System.Console.WriteLine(Tuesday);      
      System.Console.WriteLine(Wednesday);
      System.Console.WriteLine(Thursday);
      System.Console.WriteLine(Friday);      
      System.Console.WriteLine(Saturday);      
  }
}

Output

0
1
2
3
4
5
6
The above program compiles and runs successfully to give the desired output. I am sure you must have realized how much efforts this requires; you had to put the "=" sign and the value next to every variable that identifies a weekday. C# provides a convinient way for carrying out this work and that's enums! So on to enums. We will use enums to write the above program.

P3.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine(WeekDays.Sunday);
      System.Console.WriteLine(WeekDays.Monday);      
      System.Console.WriteLine(WeekDays.Tuesday);      
      System.Console.WriteLine(WeekDays.Wednesday);
      System.Console.WriteLine(WeekDays.Thursday);
      System.Console.WriteLine(WeekDays.Friday);      
      System.Console.WriteLine(WeekDays.Saturday);      
  }
}

Output

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Cool! What a detailed output! Let's spend some time on this program. Enum allows us to create a new data type. In the above program you get to see a data type WeekDays created using enum. An enum can be considered like a static object of a class. This is the reason why we are allowed to access the elements within enum by using just the name of the enum WeekDays, like WeekDays.Sunday, where WeekDays is the name of the enum and Sunday is an element of the enum WeekDays. In the WriteLine() method when we pass the element within the enum as enumName.elementName (i.e. WeekDays.Sunday)the output returned is the element name (i.e Sunday in our case). This is justified by the output that you get to see for the above program.
So what do we do to get a numerical output ?

P4.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

0
1
2
3
4
5
6
To get an integer equivalent of WeekDays.Sunday, we have casted WeekDays.Sunday to an integer and passed it as argument to the WriteLine() method. As justified by the output, the first element of the enum gets a value of 0 by default. The succeeding elements get a value in incrementing steps of 1. Thus, Monday gets a value of 1, Tuesday gets a value of 2, Wednesday gets a value of 3 and so on and so forth.

P5.cs

enum InitialDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
}

enum WeekDays : InitialDays
{
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

P5.cs(9,17): error CS1008: Type byte, sbyte, short, ushort, int, uint, long, 
or ulong expected
Error! Enums cannot be derived from other enums. Hence we are disallowed to derive enum WeekDays from InitialDays. Well, if enums cannot be derived from enums then can classes be derived from enums? Let's find it out.

P6.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo : WeekDays
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

P6.cs(12,7): error CS0509: 'Demo': cannot derive from sealed type 'WeekDays'
P6.cs(1,6): (Location of symbol related to previous error)
Error! That's because classes cannot be derived from enums. Enums are treated as sealed classes and hence all rules that are applicable to sealed classes also apply to enums.

P7.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday,
   Sunday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

P7.cs(10,4): error CS0102: The type 'WeekDays' already contains a definition 
for 'Sunday'
P7.cs(3,4): (Location of symbol related to previous error)
Error! That's because enums, like classes, cannot contain two members having the same name.

P8.cs

enum WeekDays
{
   Sunday=10,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

10
11
12
13
14
15
16
We are allowed to specify constant values for the members of the enum. In the above program we have specified a value of 10 to the first member (Sunday) of the enum. The successive members get a value one greater than the previous member's value. This is what is justified by the output.

P9.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday=10,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

0
1
2
10
11
12
13
To reiterate, we are allowed to specify constant values for the members of the enum. In the above program the first member, Sunday, of the enum gets a value of 0 by default. The successive members get a value one greater than the previous member's value. Hence, Monday gets a value of 1 and Tuesday gets a value of 2. The following member, Wednesday, is explicitly assigned a value of 10. This is what is justified by the output. The successive members get a value one greater than the previous member's value. This is what is justified by the output.

P10.cs

enum WeekDays
{
   Sunday = 10,
   Monday = 10, 
   Tuesday = 10,
   Wednesday = 10,
   Thursday = 10,
   Friday = 10,
   Saturday = 10
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

10
10
10
10
10
10
10
Explicitly assigning the same values to members of enum is allowed. This is what is justified by the output of the program.

P11.cs

enum WeekDays
{
   Sunday = 10000000000,
   Monday = 10, 
   Tuesday = 10,
   Wednesday = 10,
   Thursday = 10,
   Friday = 10,
   Saturday = 10
}

class Demo
{
  public static void Main()
  {
  }
}

Output

a.cs(4,13): error CS0266: Cannot implicitly convert type 'long' to 'int'. An'
explicit conversion exists (are you missing a cast?)
The underlying datatype for enum supported here is int. If we try and go beyond the range of values supported by the underlying data type int, we get an error which is similar to the one that we would get if we initialize an int to a value beyond its capacity. In the above program we are trying to store 10000000000 in Sunday. The underlying datatype for Sunday is int. An int variable can hold value less than 10000000000. Hence we get the error!
There are two approaches to fix the error in the above program. The first (and the obvious way is) to store a value less than 10000000000 in Sunday.

P12.cs

enum WeekDays
{
   Sunday = 100,
   Monday = 10, 
   Tuesday = 10,
   Wednesday = 10,
   Thursday = 10,
   Friday = 10,
   Saturday = 10
}

class Demo
{
  public static void Main()
  {
  }
}
The second approach is to use an underlying dataype whose capacity is such that it can afford to hold a value as large as 10000000000. This is what is done by the following program.

P13.cs

enum WeekDays : long
{
   Sunday = 10000000000,
   Monday = 10, 
   Tuesday = 10,
   Wednesday = 10,
   Thursday = 10,
   Friday = 10,
   Saturday = 10
}

class Demo
{
  public static void Main()
  {
  }
}
In the above program the integral type of enum member variables Sunday to Saturday is long.

P14.cs

enum WeekDays
{
   Sunday = 10,
   Monday = Sunday, 
   Tuesday = Monday,
   Wednesday = Tuesday,
   Thursday = Wednesday,
   Friday = Thursday,
   Saturday = Friday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine((int)WeekDays.Sunday);
      System.Console.WriteLine((int)WeekDays.Monday);      
      System.Console.WriteLine((int)WeekDays.Tuesday);      
      System.Console.WriteLine((int)WeekDays.Wednesday);
      System.Console.WriteLine((int)WeekDays.Thursday);
      System.Console.WriteLine((int)WeekDays.Friday);      
      System.Console.WriteLine((int)WeekDays.Saturday);      
  }
}

Output

10
10
10
10
10
10
10
Nothing stops us from defining the members of the enum with the predefined members of enums. In other words, in the above program, we are allowed to define an enum member Monday with a predefined member Sunday.

P15.cs

enum WeekDays
{
   Sunday = 10,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      WeekDays.Sunday = 36; 
      System.Console.WriteLine((int)WeekDays.Sunday);
  }
}

Output

P15.cs(16,7): error CS0131: The left-hand side of an assignment must be a 
variable, property or indexer
The value of an enum member cannot be changes. It behaves like a constant. In the above program, we cannot change the value of enum member Sunday from within Main(). It behaves as a constant.

P16.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
     System.Console.WriteLine(WeekDays.Wednesday.CompareTo(WeekDays.Sunday));
     System.Console.WriteLine(WeekDays.Wednesday.CompareTo(
         WeekDays.Wednesday));
     System.Console.WriteLine(WeekDays.Wednesday.CompareTo(
         WeekDays.Saturday));
  }
}

Output

1
0
-1
What if you had to compare members within enums? One may want to know if the enum member larger, smaller or equal to another enum member under consideration. To accomplish this we have made use of a method named CompareTo(). This method belongs to the Enum class. An enum is derived from the Enum class. Since Wednesday is greater than Sunday in our enum WeekDays, the output is 1. Similarly, since Wednesday is equal to Wednesday the output is 0. Likewise the output is -1 because Wednesday is less than Saturday.

P17.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine(WeekDays.Wednesday.ToString());
  }
}

Output

Wednesday
We can use the toString() function to stringify the member of the enum. So let's stringify all the members of the enum.

P18.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine(WeekDays.Sunday.ToString());
      System.Console.WriteLine(WeekDays.Monday.ToString());
      System.Console.WriteLine(WeekDays.Tuesday.ToString());
      System.Console.WriteLine(WeekDays.Wednesday.ToString());
      System.Console.WriteLine(WeekDays.Thursday.ToString());
      System.Console.WriteLine(WeekDays.Friday.ToString());
      System.Console.WriteLine(WeekDays.Saturday.ToString());
  }
}

Output

Sunday
Monday 
Tuesday
Wednesday
Thursday
Friday
Saturday
If the enum had 1000 members would you still follow the above approach? Certainly not, as it would be very a laborous task to carry out the task of typing several WriteLine() calls. Instead, the following program has a more presentable approach.

P19.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
     string [] arr =  WeekDays.GetNames(typeof(WeekDays));
     foreach(string s in arr)
        System.Console.WriteLine(s);
  }
}

Output

Sunday
Monday 
Tuesday
Wednesday
Thursday
Friday
Saturday
The static function GetNames() returns a stringified list of members within the enum WeekDays in the string array arr. The foreach loop prints the strings in the string array arr.

P20.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
        System.Console.WriteLine(WeekDays.Monday + 100);
        System.Console.WriteLine(100 + WeekDays.Monday);
  }
}

Output

101
101
C# allows the addition of enum members to numbers and vice versa because the overloaded plus operator is overloaded.

P21.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
        System.Console.WriteLine(WeekDays.Monday + WeekDays.Monday);
  }
}

Output

P21.cs(16,34): error CS0019: Operator '+' cannot be applied to operands of 
type 'WeekDays' and 'WeekDays'
Error! C# doesnot allow us to add two members of an enum as shown in the above program. In order to do so we need to overload the plus operator.
Well, if the plus operator doesnt directly work with the enum members do the operators like '==', '<' and '>' work naturally or they too have to be overloaded?

P22.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

class Demo
{
  public static void Main()
  {
      System.Console.WriteLine(WeekDays.Monday == WeekDays.Monday);
      System.Console.WriteLine(WeekDays.Monday != WeekDays.Monday);
      System.Console.WriteLine(WeekDays.Monday < WeekDays.Tuesday);
      System.Console.WriteLine(WeekDays.Monday > WeekDays.Tuesday);
  }
}

Output

True
False
True
False
The comparison operators are overloaded to work with members elements of enum as smoothly as they do with numbers. So can we use these comparison operators to compare two enums from different families? Let's find out.

P23.cs

enum WeekDays
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}

enum Days
{
   Sunday,
   Monday, 
   Tuesday,
   Wednesday,
   Thursday,
   Friday,
   Saturday
}
class Demo
{
  public static void Main()
  {
      System.Console.WriteLine(WeekDays.Monday == Days.Monday);
  }
}

Output

P23.cs(28,32): error CS0019: Operator '==' cannot be applied to operands of 
type 'WeekDays' and 'Days'
Bummer! Comparison operators don't work on members that belong to different enums.

No comments:

Post a Comment