Page 1 of 1

Working with enums in C#

#1 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1639
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Post icon  Posted 06 December 2007 - 12:44 PM

Welcome to my tutorial on working with Enumerations (enum) in C#. In this tutorial we will cover a few items involving enum's including understand anding what enum's are, learn how to create new enum's, and learn how to use the enum's we create and become familiar with some of the built in classes for using and parsing enum's in C#.

Enum's are strongly typed constants. They are essentially unique types that allow you to assign symbolic names to integral values. In the C# tradition, they are strongly typed, meaning that an enum of one type may not be implicitly assigned to an enum of another type even though the underlying value of their members are the same. Along the same lines, integral types and enums are not implicitly interchangeable. All assignments between different enum types and integral types require an explicit cast.

Enums lend themselves to more maintainable code because they are symbolic, allowing you to work with integral values, but using a meaningful name to do so. For example, what type of code would you rather work with - a set of values named North, South, East, and West or the set of integers 0, 1, 2, and 3 that mapped to the same values, respectively. Enums make working with strongly typed constants via symbolic names easy.

Enums are value types, which means they contain their own value, can't inherit or be inherited from, and assignment copies the value of one enum to another. You will see in this lesson and elsewhere that enums are used and referred to with both lower case, enum, and upper case, Enum. Strangely enough, the relationship between the two is that the C# type, enum, inherits the Base Class Library type, Enum.Use the C# type, enum, to define new enums and use the Base Class Library type, Enum, to implement static enum methods.

The .NET Framework Case Class Library contains many enums and examples of how they are used. For example, every time you put an icon on a MessageBox, you use the MessageBoxIcons enum. For a list of available enums in the BCL, look at the documentation for the Enum class and click on the Derived Classes link.

Whenever there are situations where you are using a set of related numbers in a program, consider replacing those numbers with enums. It will make a program more readable and type safe. Code section I of this tutorial contains an enum definition and code that uses that enum in a switch statement. Instead of using the numbers 0, 1, and 2 in the switch statement, the code is more meaningful through the use of the ErrorStatus enum.


// declares the enum
public enum ErrorStatus
{
	Critical,
	Fatal,
	Medium,
	Low
}

/// <summary>
/// method to retrieve the ErrorStatus and display 
/// that vaslue out
/// </summary>
static void GetErrorStatus()
{
	//create an instance of our ErrorStatus enum
	//then instantiate it to a value
	ErrorStatus err = ErrorStatus.High;

	//perform a switch status on the currenet value
	//of our ErrorStatus variable and display a
	//message based on the level of the error
	switch (err)
	{
		case ErrorStatus.Low:
			Console.WriteLine("The ErrorStatus is low.");
			break;
		case ErrorStatus.Medium:
			Console.WriteLine("The ErrorStatus is medium.");
			break;
		case ErrorStatus.High:
			Console.WriteLine("The ErrorStatus is high.");
			break;
		case ErrorStatus.Critical:
			Console.WriteLine("The ErrorStatus is critical.");
			break;
	}
	Console.ReadLine();
}



Notice that it is declared with the enum keyword, has a type identifier (ErrorStatus), and contains a comma separated list of values enclosed within curly braces. This enum is of type ErrorStatus and we use it to declare the err variable in the GetErrorStatus method. Since an enum is a value type, we can assign a value (ErrorStatus.Medium) to it directly, similar to the simple types such as int or double. Once the err variable is declared and initialized, it is used in the switch statement. Each of the case statements represent a unique member of the Volume enum.

Any time a member of the Volume enum is used, it is fully qualified with the "ErrorStatus" identifier to guarantee type safety. For example, if there were a Meat enum in scope, then Meat.Medium would definitely have different semantics than ErrorStatus.Medium. With both enums in scope, it would be ambiguous to just use the Medium identifier without type qualification. Using the type identifier ensures such mistakes are not made.

An enum is typically specified as shown in the first code example in this tutorial, but may be customized by changing its base type and member values. By default, the underlying type of of an enum is int. This default may be changed by specifying a specific base when declaring the enum. You would specify a different base if the enum was used extensively and there was an opportunity for space savings by selecting a smaller type. Another reason may be if you wanted the underlying type of the enum to correspond to another type in your program and you wanted to explicitly cast between the two without loss of precision.

There are 8 valid base enum types available to you:
  • byte
  • sbyte
  • short
  • ushort
  • int
  • uint
  • long
  • ulong

NOTE: Microsoft, in future versions of C# and the .Net Framework have toyed around with adding more base type data types for enums, but that has yet to be seen.

Another modification you can make to an enum is to set the value of any enum member. By default, the first member of an enum takes the value of zero. If this value doesn't make sense for your enum, you can change it to one or some other number. Additionally, you can change any of the members of an enum to any value that is valid for its base type.Unassigned enum members have a value that is one more than their predecessor. The next code listing will show how to change the base type of an enum and change the value of the first value in the enum.

// declares the enum
public enum ErrorStatus : byte
{
	Critical = 1,
	Fatal,
	Medium,
	Low
}
	
/// <summary>
/// method to retrieve the ErrorStatus and display 
/// that vaslue out
/// </summary>
static void GetErrorStatus()
{
	//create an instance of our ErrorStatus enum
	//then instantiate it to a value
	ErrorStatus err = ErrorStatus.High;

	//perform a switch status on the currenet value
	//of our ErrorStatus variable and display a
	//message based on the level of the error
	switch (err)
	{
		case ErrorStatus.Low:
			Console.WriteLine("The ErrorStatus is low.");
			break;
		case ErrorStatus.Medium:
			Console.WriteLine("The ErrorStatus is medium.");
			break;
		case ErrorStatus.High:
			Console.WriteLine("The ErrorStatus is high.");
			break;
		case ErrorStatus.Critical:
			Console.WriteLine("The ErrorStatus is critical.");
			break;
	}
	Console.ReadLine();
}




The ErrorStatus enum in Part II shows how to modify the base type and members of an enum. Its base type is changed to byte with the : <type> syntax following the enum identifier, ErrorStatus.This ensures that the ErrorStatus enum may only have members with values that are valid for type byte.

The first member of the ErrorStatus enum, Critical, has its value changed to 1.The same syntax, <member> = <value>, may be applied to any member of the enum. You are restricted from creating forward references, circular references, and duplicate references in enum members.

The default values of the ErrorStatus enum are Critical=0, Fatal=1, and Medium = 2, and Low=3 because the first member of an enum defaults to 0 and the following members default to one more than their predecessor. However, the ErrorStatus enum in Path II has its Critical member set to 1, which means that Medium=2, High=3 and low = 2


Enum types implicitly inherit the System.Enum type in the Base Class Library. This also means that you can use the members of System.Enum to operate on enum types. This section does just that, showing some useful tips and tricks to use with enums in your programs.

A common requirement with enums is to convert between the enum and a variable of its base type. For example, if you are getting input in the form of an int from a user or a file stream, then you can cast it to an enum and use it in a meaningful way in your program.You can also get a complete list of enum member names or enum values, which is useful if you have logic that needs to iterate through every enum member. Part III of this tutorial shows how to perform conversions between enums and their base types and how to use some of the System.Enum type members.

Now lets take a look at some tricks that can be performed when working with enum's on C#. First, before we can do anything we need to create our enum:

// declares the enum
public enum ErrorStatus : byte
{
	Critical=1,
	Fatal,
	High,
	Low
}



The next method we're going to look at is the one that will display the values of the enum in both value and name format, which it retrieves from several other methods:
  • GetFromUser
  • ListByName
  • ListByValue
The GetErrorStatus calls our other three methods all in a row. The first one it calls is GetFromUser which asks the user to select a number, 1, 2, 3, or 4:


	//Here we will do an explicit cast of
//an int value to an ErrorStatus value
public void GetFromUser()
{
	Console.WriteLine("\n----------------");
	Console.WriteLine("ErrorStatus Settings:");
	Console.WriteLine("----------------\n");

	Console.Write(@"1 - Low
					2 - Medium
					3 - Critical
					4 - Fatal
					Please select one (1, 2, or 3): ");

	// get value user provided
	string userInput = Console.ReadLine();
	int inputConversion = Int32.Parse(userInput);

	// perform explicit cast from
	// int to ErrorStatus enum type
	ErrorStatus errStatus = (ErrorStatus)inputConversion;

	Console.WriteLine();

	// make decision based
	// on enum value
	switch (errStatus)
	{
		case ErrorStatus.Low:
			Console.WriteLine("The ErrorStatus is currently low.");
			break;
		case ErrorStatus.Medium:
			Console.WriteLine("The ErrorStatus is currently medium");
			break;
		case ErrorStatus.High:
			Console.WriteLine("The ErrorStatus is currently critical");
			break;
		case ErrorStatus.Fatal:
			Console.WriteLine("The ErrorStatus is currently fatal");
			break;
	}

	Console.WriteLine();
}




We have 2 methods left to show the tricks you can play with enums, ListByName, and ListByValue. First lets took at the ListByName method:

// iterate through ErrorStatus enum by name
/// <summary>
/// method to iterate through our enum values
/// name by name
/// </summary>
public void ListByName()
{
	Console.WriteLine("\n---------------------------- ");
	Console.WriteLine("Names in ErrorStatus enum:");
	Console.WriteLine("----------------------------\n");

	//first we need to get a list of enum names
	// from the ErrorStatus enum, then figure out the
	//numeric value and display its name
	foreach (string val in Enum.GetNames(typeof(ErrorStatus)))
	{
		//loop through our enum and display all the
		//name values in the enumeration
		Console.WriteLine("ErrorStatus Member: {0}\n Value: {1}", val, (byte)Enum.Parse(typeof(ErrorStatus), val));
	}
}



Notice in this method we use methods such as Enum.Parse. This method is used to converts the string representation of the name or numeric value to the proper enumerated value, then we convert that to the appropriate data type, byte for display.

The last method we'll look at is the ListByValues method. With this one we perform almost the same exact process that we do in ListByName, except this time we use Enum.GetByName MEthod so we can get the name of the current iteration of the loop and display the value for that enum value's name:

// iterate through ErrorStatus enum by value
/// <summary>
/// method for us to iterate through our enum
/// value by value
/// </summary>
public void ListByValue()
{
	Console.WriteLine("\n----------------------------- ");
	Console.WriteLine("Values in ErrorStatus enum:");
	Console.WriteLine("-----------------------------\n");

	//first we need to get a list of enum names
	// from the ErrorStatus enum, then figure out the
	//numeric value and display its value
	foreach (byte val in Enum.GetValues(typeof(ErrorStatus)))
	{
		Console.WriteLine("ErrorStatus Value: {0}\n Member: {1}", val, Enum.GetName(typeof(ErrorStatus), val));
	}
}



Though this isn't all that can be done with enum's, I could literally go on for days with he different tricks and tips we can use for manipulating enums. I really hope you found this tutorial useful and informative, and I thank you for

reading.

This post has been edited by PsychoCoder: 08 December 2007 - 10:43 AM


Is This A Good Question/Topic? 1
  • +

Replies To: Working with enums in C#

#2 Nayana  Icon User is offline

  • DIC Hawk - 나야나 नयन:
  • member icon

Reputation: 31
  • View blog
  • Posts: 824
  • Joined: 14-November 07

Posted 06 December 2007 - 11:02 PM

Nice comprehensive tutorial.

First, an error:
You didn't close your first [ code ] tag.

Now a suggestion:
Maybe you could have something about using them as flags,

e.g.
enum AlarmAction {
  nothing = 0,
  callDaPolice = 1,
  callSecurity = 2,
  soundAlarms = 4,
  lockDoors = 8
}



And you can use them like:

Floor[i].Sensor[j].Action = callDaPolice | lockDoors;

But I'm sure you could explain it better than me :)
Was This Post Helpful? 0
  • +
  • -

#3 Iouri  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 09-August 08

Posted 20 February 2009 - 03:46 PM

Thanks a lot for this tut, very helpful, is there any possibility to add a "summary" for each enum though? So when the little VS box pop-ups, I can see more detailed information for every enum member. :)

This post has been edited by Iouri: 20 February 2009 - 03:47 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1