Introduction
Enum
s are very useful and provide a convenient method for defining standard lists or options such as the DayOfWeek
or the FormBorderStyle
property in Windows Forms.
Background
I use Enum
s wherever possible in my code and usually provide GUI editing functions using a ComboBox
or CheckedListBox
. This is OK for most simple Enum
types, however Enum
s can actually be quite complex as explained below and something more than a basic CheckListBox
may be required for editing.
Many simple Enum
s are defined using just a list of element names as shown here. If required, you can optionally specify the underlying data type used to store the actual value of the Enum
but this is not required and will default to int
.
public enum Vehicles
{
None,
Cars,
MotorCycles,
Trucks,
Buses
}
If you don't specify the numeric value of each element, the compiler will automatically supply these values starting at 0
for the first item and incrementing by one for each subsequent item. If required however, you can specify the actual numeric value of each item as shown below:
public enum Vehicles : int
{
None = 0,
Cars = 1,
MotorCycles = 2,
Trucks = 3,
Buses = 4
}
Here lies the first interesting point... you can specify multiple elements with the same numeric value as shown below. Notice that SaloonCars
and SportsCars
have the same numeric value of 1
.
public enum Vehicles : int
{
None = 0,
SaloonCars = 1,
SportsCars = 1,
MotorCycles = 2,
Trucks = 3,
Buses = 4
}
Flags Enums
With simple Enum
types, you can only select one value from the list of values. Flags type Enum
s are decorated with the FlagsAttribute ([Flags])
. With Flags Enum
s, each element within the Enum
represents one or more bits set within the underlying value. As with simple Enum
s, more than one element can have the same numeric value. Elements within Flags Enums
can also represent a set of other values within the Enum
as shown below:
[Flags]
public enum Targets: int
{
Users = 1,
Computers = 2,
UserAndComputer= 3,
Servers = 4,
All = 7
}
Notice that element 'All
' (7) represents a binary value of 111
which effectively will match Users, Computers and Servers.
If you set the value of an Enum
to a value that does not match one or more of the defined elements, you will not get an Exception
and when calling the ToString()
method, it will display the string
representation of the numeric value rather than the list of Enum
names. Developers often have to include code to detect this situation and throw ArgumentOutOfRange
Exceptions for invalid values. Also note that not all Enum
s have a value representing numeric 0
so even the default value of an Enum
may not match any of the defined flag names.
var targets = Targets.Users | Targets.Servers;
Console.WriteLine(targets);
var targets = Targets.Users | Targets.Computer;
Console.WriteLine(targets);
var targets = (Targets)8;
Console.WriteLine(targets);
targets = (Targets)0;
Console.WriteLine(targets);
The Enum Editor
I have developed a Universal Enum
editor control based on the CheckistBox
control. It will work correctly with Enum
s for all of the supported underlying data types. It handles both simple and flags Enums
. If required, simple Enum
types will be rendered as RadioButtons
rather than CheckBoxes
.
The Editor also handles Enum
s which have multiple elements with the same underlying values. An example of this is the System.Security.AccessControl.FileSystemRights Enum
. This is a complex Enum
used to specify the file system access rights and relates very closely to the Window file system security dialogs.
Using the Code
To use the code, simply unzip the demo project and run it. The editor control is the 'EnumEditor
' custom control derived from the CheckListBox
control.
Points of Interest
I originally thought that Enum
s were quite simple but the more I investigated, I realized that there are a lot more subleties than I first thought and so I tried quite a few versions of the Enum
Editor before I was finally happy.
History
- Rev 1: The
ItemHeight
property did not work correctly