OOP With C Day6
OOP With C Day6
Table of Contents
Introduction
My article will explain enum datatype in c#. We’ll learn by doing hands on lab and not only by theory. We’ll
explore the power of enum and will cover almost every scenario in which we can use enum. We’ll follow a
practical approach of learning to understand this concept. We may come across complex examples to
understand the concept more deeply.
Enums (The definition):
Let’s start with the definition taken from MSDN
“The enum keyword is used to declare an enumeration, a distinct type that consists of a set of named
constants called the enumerator list.
Usually it is best to define an enum directly within a namespace so that all classes in the namespace can access
it with equal convenience. However, an enum can also be nested within a class or struct.
By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1.
For example, in the following enumeration, Sat is 0, Sun is 1, Mon is 2, and so forth.”
Pre-requisites:
I expect that my readers of this article should have very basic knowledge of C# and I always wish that my
readers should enjoy while reading this article. Also keep writing programs by yourself that are given as
example in this article, to get the hands on and understand the concept more deeply.
A Practical Approach:
Enum plays almost the same responsibility as the class does, i.e. creating a new data type, and it exists at the
same level as class, interfaces or structs.
Just open your visual studio and add a console application named Enums. You’ll get Program.cs class.
Note: Each and every code snippet in this article is tried and tested.
Program.cs:
namespace Enums
{
class Program
{
static void Main(string[] args)
{
}
}
enum Color
{
Yellow,
Blue,
Brown,
Green
}
}
In the above mentioned example, we created a new datatype with the help of enum. The datatype is Color
having four distinct values Yellow, Blue, Brown and Green. The text that we write inside the declared enum
could be anything of your wish; it just provides a custom enumerated list to you.
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Color.Yellow);
Console.ReadLine();
}
}
enum Color
{
Yellow,
Blue,
Brown,
Green
}
}
Output: Yellow
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine((int)Color.Yellow);
Console.ReadLine();
}
}
enum Color
{
Yellow,
Blue,
Brown,
Green
}
}
Output: 0
We see that enum is called as static variables, so an enum can be considered here as static objects. Therefore
other enums in the above example can be declared in the same way as Yellow, like Blue can be declared as
Color.Blue. The output in above two examples we see is 0 when we type cast and Yellow without typecasting,
hence we see here that its behaviour is very similar to an array where Yellow has a value 0, similarly Blue has a
value 1, Brown: 2,Green:3.
Therefore when we do Color.Yellow, it’s like displaying a number 0, so from this can we infer that an enum
represents a constant number, therefore an enum type is a distinct type having named constants.
Point to remember: An enum represents for a constant number, and an enum type is known as a distinct type
having named constants.
Program.cs:
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine((byte)Color.Yellow);
Console.WriteLine((byte)Color.Blue);
Console.ReadLine();
}
}
enum Color:byte
{
Yellow,
Blue,
Brown,
Green
}
}
Output:
0
1
Note: Each and every code snippet in this article is tried and tested.
The only change we did here is that we specified the type to the underlying enum that we declared. The
default datatype for the enum is int, here we have specified the data type as byte and we get the result.
There are more data types that can be specified for enum like long, ulong, short, ushort, int, uint, byte and
sbyte.
Point to remember: We can’t declare char as an underlying data type for enum objects because char stores
Unicode characters, but enum objects data type can only be number.
Inheritance in enum:
Program.cs:
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine((byte)Color.Yellow);
Console.WriteLine((byte)Color.Blue);
Console.ReadLine();
}
}
enum Color:byte
{
Yellow,
Blue,
Brown,
Green
enum Shades:Color
{
}
}
Output:_
Compile time error: Type byte, sbyte, short, ushort, int, uint, long, or ulong expected
We clearly see here enums can’t be derived from any other type except that of mentioned in the error.
Point to remember: enum can’t be derived from any other type except that of type byte, sbyte, short, ushort,
int, uint, long, or ulong
Let’s derive a class from enum, call it class Derived, so our code,
Program.cs:
class Program
{
static void Main(string[] args)
{
Console.WriteLine((byte)Color.Yellow);
Console.WriteLine((byte)Color.Blue);
Console.ReadLine();
}
}
Enum:
enum Color:byte
{
Yellow,
Blue,
Brown,
Green
Derived.cs:
class Derived:Color
{
Compile time error: 'Enums.Derived': cannot derive from sealed type 'Enums.Color'
Program.cs:
using System;
namespace Enums
{
internal enum Color: System.Enum
{
Yellow,
Blue
}
Output:
Compile time error: Type byte, sbyte, short, ushort, int, uint, long, or ulong expected
Point to remember:The enum type is implicitly derived from System.Enum and so we cannot explicitly derive
it from System.Enum.
To add more, enum is also derived from three interfaces IComparable, IFormattable and IConvertible
IComparable :
Let’s check,
Program.cs:
using System;
namespace Enums
{
internal enum Color
{
Yellow,
Blue,
Green
}
Output:
-1
-1
1
0
Sometimes we may get into situations where we have large number of enums defined and we want to
compare the values of enum to each other to check if they are smaller , larger or equal value to one another.
Since all enum implicitly derive from Enum class that implements tha interface IComparable, so they all have a
method CompareTo(), that we just used in above example. The method being non static has to be used
through a member.Yellow has value 0, Blue as 1 and Green as 2.In the first statement, when Color.Yellow
comared to Color.Blue, value of Yellow is smaller than Blue hence -1 returned, same applied for the second
statement when Color.Blue compared to Color.Green.Green has larger value i.e. 2 than that of Color.Blue
having value 1 only. In third statement i.e. vice versa of first statement, we get the result of camparison as 1,
because Blue is larger than Yellow.In last statement where Color.Green compares to itself, we undoubtedly
get the value 0.
So value -1 means the value is smaller, 1 means value is larger and 0 means equal values for both the enum
members.
using System;
namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}
Output:
Compile time error : Operator '==' cannot be applied to operands of type 'int' and 'Enums.Color'
In above example we tried to compare an int type to Enum type and resulted in a compile time error. Since
enum acts as an individual data type so it cannot be directly compared to an int, however, we can typecast the
enum type to int to perform comparison, like in below example,
Program.cs:
using System;
namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}
Output: my color
IFormattable
Program.cs:
using System;
namespace Enums
{
internal enum Color
{
Yellow,
Blue,
Green
}
Output:
00000002
2
Format is the method derived from IFormatter interface. It’s a static method so can be used directly with the
enum class defined as Color. It’s first parameter is the type of the enum class, second is the member that has
to be formatted and third is the format i.e. hexadecimal or decimal, like we used in above example, and we
got a positive result output too.
IConvertible :
using System;
namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}
Output:
Yellow
Blue
Green
Note: Each and every code snippet in this article is tried and tested.
GetNames is a static method that accepts Type i.e. instance of type as a parameter and in return gives an array
of strings. Like in above example, we had array of 3 members in our enum, therefore there names is displayed
one by one.
Another example:
Program.cs
using System;
namespace Enums
{
enum Color
{
Yellow,
Blue,
Green
}
Output:
Blue
Green
As we see in above example, we converted an enum type to staring type and got an output too, so, numerous
predefined conversion methods can be used to convert enum from one data type to another.
Point to remember: A numerous predefined conversion methods can be used to convert enum from one data
type to another.
Program.cs:
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine((byte)Color.Yellow);
Console.WriteLine((byte)Color.Blue);
Console.ReadLine();
}
}
enum Color
{
Yellow,
Blue,
Brown,
Green,
Blue
}
}
Output:
Compile time error: The type 'Enums.Color' already contains a definition for 'Blue'
In the above example we just repeated the enum member Blue of Color, and we got a compile time error,
hence we now know that an enum cannot contain two members having same name.By default if the first
value is not specified, first member takes the value 0 and increments it by one to succeeding members.
Program.cs:
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine((int)Color.Yellow);
Console.WriteLine((int)Color.Blue);
Console.WriteLine((int)Color.Brown);
Console.WriteLine((int)Color.Green);
Console.ReadLine();
}
}
enum Color
{
Yellow =2,
Blue,
Brown=9,
Green,
}
}
Output:
2
3
9
10
Surprised!, We can always specify the default constant value to any enum member, here we see, we specified
value 2 to yellow, so as per law of enum, the value of blue will be incremented by one and gets the value 3.We
again specified 9 as a default value to Brown, and so its successor Green gets incremented by one and gets
that value 10.
Program.cs:
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
}
}
enum Color:byte
{
Yellow =300 ,
Blue,
Brown=9,
Green,
}
}
Output:
We just derived our enum from byte, we know we can do that . We then changed the value of yellow from 2
to 300, and we resulted in a compile time error. Since here our underlying data type was byte , so it is as
simple as that, that we can not specify the value to enum members which exceeds the range of underlying
data types.The value 300 is beyond the range of byte.It is similar to assigning the beyond range value to a byte
data type variable.
Another example:
Program.cs:
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine((int)Color.Yellow);
Console.WriteLine((int)Color.Blue);
Console.WriteLine((int)Color.Brown);
Console.WriteLine((int)Color.Green);
Console.ReadLine();
}
}
enum Color
{
Yellow = 2,
Blue,
Brown = 9,
Green = Yellow
}
}
Output:
2
3
9
2
Here we initialized Green to Yellow, and we did not get any error, so we see, more than one enum members
can be initialized a same constant value.
Point to remember: More than one enum members can be initialized a same constant value.
Program.cs:
using System;
namespace Enums
{
class Program
{
static void Main(string[] args)
{
Color.Yellow = 3;
}
}
enum Color
{
Yellow = 2,
Blue,
Brown = 9,
Green = Yellow
}
}
Output:
Compile time error: The left-hand side of an assignment must be a variable, property or indexer
In the above example, we tried to initialize the enum member out of the scope of defined enum i.e. in another
class, and got a compile time error.We must not forget that an enum acts as a constant, which cannot change
its value.
Point to remember: An enum acts as a constant, so its value cannot be changed once initialized.
Readability:
Program.cs:
using System;
namespace Enums
{
internal enum Color
{
Yellow,
Blue,
Brown,
Green
}
}
}
}
}
Output:
Yellow
Brown
Green
Here, in above example we have declared an enum Color containing various color members.There is a class
named program that contains a static method named CheckColor, that has a switch statement checking color
on the basis of passed parameter to the method i.e. Enum Color.In Main method we try to access that
CheckColor method, passing various parameters. We see that the the switch statement in CheckColor method
can take any of the datatype passed and in return case statements use name of that type and not the plain int
number to compare the result.e see that this made our program more readable. So enum plays an important
role in making the [rogram more readable and structured, easy to grasp.
Circular dependency:
Program.cs:
using System;
namespace Enums
{
internal enum Color
{
Yellow=Blue,
Blue
}
Output:
Compile time error: The evaluation of the constant value for 'Enums.Color.Yellow' involves a circular
definition
Like constants we also cannot have circular dependency in enums. We assigned value Blue to Yellow, and Blue
in turn is incremented by one as a next enum member, this results in a circular dependency of Blue to yellow,
and resulted in error, c# is smart enough to catch these kind of tricks.
Diving Deep:
Program.cs:
using System;
namespace Enums
{
enum Color
{
Note: Each and every code snippet in this article is tried and tested.
Output:
Compile time error:
To cast a negative value, you must enclose the value in parentheses
'Enums.Color' is a 'type' but is used like a 'variable'
In the above example, we are casting a negative value to enum, but the compiler says that while casting a
negative value, we must keep that in parenthesis. It’s not strange, as C# knows that “-” is also a unary
operator, that while using above code may create a confusion for compiler that we are using subtraction or
typecasting a negative value. So always use parenthesis while typecasting negative values.
Lab2:
Program.cs:
using System;
namespace Enums
{
enum Color
{
value__
}
}
}
}
Output:
Compile time error: The enumerator name 'value__' is reserved and cannot be used
We clearly see here that we have value__ as reserved member for the enumerator. C# compiler like this
keyword has large number of reserved inbuilt keywords.
It may keep this reserved keyword to keep track of the enum members internally but not sure.
Summary:
1) An enum represents for a constant number, and an enum type is known as a distinct type having
named constants.
2) We can’t declare char as an underlying data type for enum objects because char stores Unicode
characters, but enum objects data type can only be number.
3) An enum can’t be derived from any other type except that of type byte, sbyte, short, ushort, int, uint,
long, or ulong.
4) By default enum is a sealed class and therefore sticks to all the rules that a sealed class follows, so no
class can derive from enum i.e. a sealed type.
5) The enum type is implicitly derived from System.Enum and so we cannot explicitly derive it from
System.Enum.
6) enum is also derived from three interfaces IComparable, IFormattable and IConvertible.
7) A numerous predefined conversion methods can be used to convert enum from one data type to
another.
8) More than one enum members can be initialized a same constant value.
9) An enum acts as a constant, so its value cannot be changed once initialized.
10) The enumerator name 'value__' is reserved and cannot be used
Conclusion:
With this article we completed almost all the scenarios related to enum. We did a lot of hands-on lab to clear
our concepts. I hope my readers now know by heart about these basic concepts and will never forget them.
About Author
Akhil Mittal works as a Sr. Analyst in Magic Software and have an experience of more than 8 years in C#.Net. He is a
codeproject and a c-sharpcorner MVP (Most Valuable Professional). Akhil is a B.Tech (Bachelor of Technology) in
Computer Science and holds a diploma in Information Security and Application Development from CDAC. His work
experience includes Development of Enterprise Applications using C#, .Net and Sql Server, Analysis as well as Research
and Development. His expertise is in web application development. He is a MCP (Microsoft Certified Professional) in
Web Applications (MCTS-70-528, MCTS-70-515) and .Net Framework 2.0 (MCTS-70-536).