C# enum Examples

Store named and magic constants with enums. Use enums in collections, if and switch.

Enum. In the forest a flower grows. This flower has many attributes. It is blooming. It is purple (not blue or yellow). A gentle wind passes through the region.

With an enum, we can classify this plant. Consider that flowers come in all colors. It could use FlowerColor.Purple. Another one could be Blue.

Enum example. Here is an enum that expresses importance. An enum type internally contains an enumerator list. The values (like Trivial and Critical) are ints like 1 and 4.

Int: The underlying value of this enum is the default, which is int. When we use an Importance variable, we are using an int.

If: We test the enum value with an if-statement that includes an if-else block. The value is Critical, so "True" is printed.

C# program that uses enums using System; class Program { enum Importance { None, Trivial, Regular, Important, Critical } static void Main() { // ... An enum local variable. Importance value = Importance.Critical; // ... Test against known Importance values. if (value == Importance.Trivial) { Console.WriteLine("Not true"); } else if (value == Importance.Critical) { Console.WriteLine("True"); } } } Output True

Enum advantages. With an enum, magic constants are separate. This modular design makes things easier to understand. Fewer bugs will be introduced.

Example: Consider this program—the color Blue is supposed to have the value 9001. We can store this in an enum to ease maintenance.

IntelliSense: Enums can be used with IntelliSense in Visual Studio. This feature will guess the value you are typing.

Press tab: We can simply press tab and select the enum type we want. This is an advantage to using enum types.

C# program that shows enum advantages using System; enum CaseColor { Uncolored = 0, Red = 8001, Blue = 9001 } class Program { static void Main() { // This makes sense to read. Console.WriteLine("COLOR: {0}, {1}", CaseColor.Blue, (int)CaseColor.Blue); // This is more confusing to read. Console.WriteLine("COLOR: {0}, {1}", "Blue", 9001); } } Output COLOR: Blue, 9001 COLOR: Blue, 9001

Debugger. We examine what enums look like in the Visual Studio debugger. We see that enums are strongly-typed. You cannot assign them to just any value.

Note: The debugger shows that "tagValue" is of type Program.TagType. Internally it is represented as an integer.

C# program that uses enums with Debugger using System; class Program { enum TagType { None, BoldTag, ItalicsTag, HyperlinkTag, } static void Main() { // Specify a tag instance. TagType tagValue = TagType.BoldTag; if (tagValue == TagType.BoldTag) { // Will be printed. Console.WriteLine("Bold"); } if (tagValue == TagType.HyperlinkTag) { // This is not printed. Console.WriteLine("Not true"); } } } Output Bold

Strings. We convert enums to strings for display on the Console. Enum values always have a name, such as TagType.None (in the above example).

Tip: To print out the enum values, you can call ToString on the enum variable in a program.

Also: Another method such as Console.WriteLine can automatically call the ToString method.

ToString: Internally, ToString invokes methods that use reflection to acquire the string representation.

Enum ToString
C# program that uses enums with Console.WriteLine class Program { enum Visibility { None, Hidden = 2, Visible = 4 } enum AnimalType { None, Cat = 1, Dog = 2 } static void Main() { // ... Two enum variables. AnimalType animal = AnimalType.Dog; Visibility visible = Visibility.Hidden; // ... Use Console.WriteLine to print out heir values. System.Console.WriteLine(animal); System.Console.WriteLine(visible); } } Output Dog Hidden

Switch. We often use if-statements with enums. But switch is another option. And switch is sometimes compiled to more efficient IL.Switch Enum

IsFormat: This method works as a filter that tells us something about sets of enum values—it contains a switch statement.

Logic: We can separate the logic here instead of repeating ourselves. This helps clarify the program logic.

C# program that uses enums in switch using System; class Program { enum FormatType { None, BoldFormat, // Is a format value. ItalicsFormat, // Is a format value. Hyperlink // Not a format value. } static void Main() { // ... Test enum with switch method. FormatType formatValue = FormatType.None; if (IsFormat(formatValue)) { // This is not reached, as None does not return a true value in IsFormat. Console.WriteLine("Error"); } // ... Test another enum with switch. formatValue = FormatType.ItalicsFormat; if (IsFormat(formatValue)) { // This is printed, as we receive true from IsFormat. Console.WriteLine("True"); } } /// <summary> /// Returns true if the FormatType is Bold or Italics. /// </summary> static bool IsFormat(FormatType value) { switch (value) { case FormatType.BoldFormat: case FormatType.ItalicsFormat: { // These 2 values are format values. return true; } default: { // The argument is not a format value. return false; } } } } Output True

Default. Values are always initialized to zero when they are fields of a class. Upon class creation, an enum field will also be initialized to zero (and the equivalent value).

Tip: To make enums valid, always use the default value of zero. This way, we can test for the default value of fields.

Sometimes: This issue is not worth fixing. But it is often useful for verifying correctness.

Also: You can place a semicolon at the end of an enum block (but this is not required or helpful usually).

C# program that shows default enum value using System; enum CatFurColor { None, Orange, Grey }; class Program { static CatFurColor _color; static void Main() { // The enum is a field, so it has its default value of None. Console.WriteLine("DEFAULT ENUM VALUE: {0}", _color); } } Output DEFAULT ENUM VALUE: None

Collections. Here we apply the Stack collection in the .NET Framework. With Stack, we can develop a parser that keeps the most recently encountered enum value on the top.

Stack: The Stack here can only have TagType values added to it. This is an example of type checking and validation.


Pop: With the Pop method we get the top element from the stack. This is of type TagType.ItalicsTag.

Result: In the execution of this program, the stack has two enums added and one removed.

C# program that uses enums with Stack using System.Collections.Generic; class Program { enum TagType { None, // integer value = 0 BoldTag, // 1 ItalicsTag, // 2 HyperlinkTag, // 3 } static void Main() { // Create a Stack of enums. var stack = new Stack<TagType>(); // ... Add enum values to our Stack. stack.Push(TagType.BoldTag); // Add bold. stack.Push(TagType.ItalicsTag); // Add italics. // ... Get the top enum value. TagType thisTag = stack.Pop(); // Get top tag. System.Console.WriteLine("POP RESULT: " + thisTag); // Peek at the top. var peeked = stack.Peek(); System.Console.WriteLine("PEEK RESULT: " + peeked); } } Output POP RESULT: ItalicsTag PEEK RESULT: BoldTag

Type. An enum has an underlying type. Each time we use the enum, we are using the underlying type. The enum has syntactic sugar on top.

Int: Enums are by default an int type, but we can adjust this to a different numeric type.

Byte: Here we create an enum with a type of byte. This is sometimes useful on small enums. A byte can only contain 256 different values.


Memory: The CoffeeSize enum will use memory equivalent to a byte. This can make classes more efficient and smaller.

C# program that uses underlying type using System; class Program { enum CoffeeSize : byte { None, Tall, Venti, Grande }; static void Main() { // ... Create a coffee size local. CoffeeSize size = CoffeeSize.Venti; Console.WriteLine(size); } } Output Venti

GetUnderlyingType. We can determine an enum's type (like int) at runtime. Enum.GetUnderlyingType, a static method, determines the underlying type.Static

Next: We declare an enum Importance. For this example it uses an underlying type of byte.

Then: When the GetUnderlyingType method is called, the System.Byte type is returned.

C# program that uses GetUnderlyingType using System; class Program { enum Importance : byte { Low, Medium, High }; static void Main() { // Determine the underlying type of the enum. Type type = Enum.GetUnderlyingType(typeof(Importance)); Console.WriteLine(type); } } Output System.Byte

Null, none. An enum value cannot be null. It is a value type like an int. To avoid the "cannot convert null" error, use a special None constant as the first enum item.
C# program that causes null error enum Color { None, Blue, Red } class Program { static void Main() { Color c = null; } } Output Error CS0037 Cannot convert null to 'Color' because it is a non-nullable value type C# program that uses None enum enum Color { None, Blue, Red } class Program { static void Main() { Color c = Color.None; } }

Flags. The C# language allows us to specify a Flags attribute on an enum. This enables the enum to be used as a bit field. We can use combinations of enum values this way.Enum Flags

Here: We have an enum called DataInfo that has 4 different flag values. We set 2 of them at once in Main().

And: In the if-statement, we find that OptionA and OptionC are set to true, but OptionB is not set. This is the correct result.

C# program that shows enum flags using System; class Program { [Flags] enum DataInfo { None = 0, OptionA = 1, OptionB = 2, OptionC = 4, } static void Main() { var info = DataInfo.OptionA | DataInfo.OptionC; // See if current flag is set. if ((info & DataInfo.OptionA) == DataInfo.OptionA && (info & DataInfo.OptionB) != DataInfo.OptionB && // Not OptionB. (info & DataInfo.OptionC) == DataInfo.OptionC) { Console.WriteLine("Has OptionA, OptionC, but not OptionB."); } } } Output Has OptionA, OptionC, but not OptionB.

Benchmark, enum. Enums are fast. They are almost never a performance concern. They are just syntactic sugar on a type like int, which is also fast.

Version 1: This version of the code tests for an enum value. We run it in a tight loop for many iterations.

Version 2: This codes tests an int. By comparing these versions of the code, we can see any possible performance impact from enums.

Result: The enum test takes the same amount of time as the int test—the enum carries no performance penalty over int.

C# program that benchmarks enum, int using System; using System.Diagnostics; class Program { enum TestType { None, Valid, Invalid } const int _max = 10000000; static void Main() { // Version 1: use enum in if-statement. var s1 = Stopwatch.StartNew(); var temp1 = TestType.Valid; for (int i = 0; i < _max; i++) { if (temp1 == TestType.Invalid) { return; } } s1.Stop(); // Version 2: use int in if-statement. var s2 = Stopwatch.StartNew(); var temp2 = 0; for (int i = 0; i < _max; i++) { if (temp2 == 2) { return; } } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } } Output 0.27 ns if enum 0.27 ns if int

IL, enum. We can determine the exact performance of enums by examining the IL (intermediate language) of a compiled C# program. Enums are loaded with ldc.i4.

And: This means "load constant integer of 4 bytes." So an enum of just a constant 4-byte integer, exactly like any other const int.

Program: This has an enum, 3 const ints, and 3 static readonly ints. The IL shows how the values are loaded onto the evaluation stack.

Results: Enums and const ints are loaded with ld.c, so they perform the same. But static ints are loaded with ldsfld, which is slower.

C# program that uses enum, const, fields using System; enum Test { Cat, Dog, Rabbit } class Program { const int _cat = 0; const int _dog = 1; const int _rabbit = 2; static readonly int _cat2 = 0; static readonly int _dog2 = 1; static readonly int _rabbit2 = 2; static void Main() { Method(Test.Cat); Method(Test.Dog); Method(Test.Rabbit); Method(_cat); Method(_dog); Method(_rabbit); Method(_cat2); Method(_dog2); Method(_rabbit2); } static void Method(Test test) { } static void Method(int value) { } } Compiled Main method from program: IL .method private hidebysig static void Main() cil managed { .entrypoint .maxstack 1 L_0000: ldc.i4.0 L_0001: call void Program::Method(valuetype Test) L_0006: ldc.i4.1 L_0007: call void Program::Method(valuetype Test) L_000c: ldc.i4.2 L_000d: call void Program::Method(valuetype Test) L_0012: ldc.i4.0 L_0013: call void Program::Method(int32) L_0018: ldc.i4.1 L_0019: call void Program::Method(int32) L_001e: ldc.i4.2 L_001f: call void Program::Method(int32) L_0024: ldsfld int32 Program::_cat2 L_0029: call void Program::Method(int32) L_002e: ldsfld int32 Program::_dog2 L_0033: call void Program::Method(int32) L_0038: ldsfld int32 Program::_rabbit2 L_003d: call void Program::Method(int32) L_0042: ret }

Parse. Sometimes we have a string value that we want to convert to an equivalent enum. This could happen when accepting user input.

Tip: When using the .NET Framework, calling a built-in method to do conversions (where one exists) is usually best.

Enum.Parse: The tricky part of using this method involves typeof and casting. It is best to avoid this if possible.


GetName, Getnames. Built-in methods get strings that represent enums. With GetName, we can get the name for an enum value. With GetNames we get all the string representations at once.Enum.GetName

Format enums. It is possible to format the values stored in enums in different ways. We can display an integer representation, or a hex representation.Enum.Format

Arrays. Enums are values. We can use enums to index arrays. This approach is useful for some kinds of tables or data structures in programs.Enum Array

Memory. Suppose we develop a class that has an enum field. The underlying type of this enum contributes to how much memory the class will use.

Memory, continued. A smaller type (such as byte) will make class instances that hold the enum smaller. Thousands of class instances are required before this optimization is important.

A review. Enums enhance clarity and reduce the probability of invalid constants. We use them to represent constant values (such as integers) in a consistent way.
Dot Net Perls
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to