Introduction
Working with enums is a very interesting option in several situations, that one that I prefer the most is to avoid hardcoding a string. Another interesting one for me is the possibility of modifying the behaviour of a class or a control giving it a sequence of orders with an enum that accepts more than one value.
The Source of the Idea
The first time when I was developing with Reflection, I discovered the way the System.Type.GetType().GetMethod() method has a parameter whose type is the enum System.Reflection.BindingFlags, and this method accepts more than one value or the Enum if necessary to specify the behaviour of the method.
System.Collections.ArrayList list = new System.Collections.ArrayList ();
System.Type type = list.GetType();
System.Reflection.MethodInfo mi = type.GetMethod
( "Sort", System.Reflection.BindingFlags.IgnoreCase |
System.Reflection.BindingFlags.Public );
mi.Invoke ( list, new object [] { } );
Background
When I saw the values of the members of the enums and some documentation about it, I clearly noticed that the trick is to develop an enum with values such that the addition of any combination is unique.
This is the way most of the .NET Framework enums are defined. To be precise, most of those that I have seen, as for example the Binding Flags enum, are defined with values in a series of 2^n, having 0 as default value.
public enum PlanesTypes
{
NoPlane = 0, F15_Eagle = 1, F18A_Hornet = 2, F14 = 4, MIG29_Fulcrum = 8, F16_Falcon = 16, F127_Phantom = 32 }
public enum DaysOfWeek
{
NoDay = 0, Monday = 1, Tuesday = 2, Wednesday = 4, Thursday = 8, Friday = 16, Saturday = 32, Sunday = 64 }
Declare an enum this way, you always can add as many values of the enum as you like and you can be sure you will be able to recover the selected values when needed.
SetMyFavoriteDaysOfTheWeek ( ( DaysOfWeek ) 13 );
SetMyFavoriteDaysOfTheWeek
( DaysOfWeek.Friday | DaysOfWeek.Saturday | DaysOfWeek.Sunday );
SetMyFavoriteDaysOfTheWeek ( DaysOfWeek.Saturday | DaysOfWeek.Sunday );
SetMyFavoriteDaysOfTheWeek ( DaysOfWeek.Monday | DaysOfWeek.Tuesday |
DaysOfWeek.Wednesday | DaysOfWeek.Thursday | DaysOfWeek.Friday );
What I have done is a static function that given an enumType and a value returns a System.Collections.ArrayList with the values resulting from desegregating the enum value given as a parameter.
public class EnumReader
public class EnumReader
{
public static System.Collections.ArrayList GetValuesFromEnum
( System.Type EnumType, int EnumValue )
{
System.Array EnumValues = System.Enum.GetValues ( EnumType );
System.Collections.ArrayList valuesList =
new System.Collections.ArrayList ( EnumValues.Length );
System.Collections.ArrayList SelectedList =
new System.Collections.ArrayList ( );
System.Collections.IEnumerator enumerator = EnumValues.GetEnumerator();
while ( enumerator.MoveNext() )
valuesList.Add ( ( int ) enumerator.Current );
valuesList.Sort ( new ReverseOrder() );
enumerator = valuesList.GetEnumerator();
while ( enumerator.MoveNext() )
{
if ( EnumValue >= ( int ) enumerator.Current )
{
EnumValue -= ( int ) enumerator.Current;
SelectedList.Add ( ( int ) enumerator.Current );
}
}
return SelectedList;
}
internal class ReverseOrder : System.Collections.IComparer
{
public int Compare ( object x, object y )
{
return ( ( int ) y ).CompareTo ( ( int ) x );
}
}
}
In the image below, it can easily be seen that the binary addition can be decomposed in the single values of the enum. And it is also clear that if the values of the enum are declared as 2^n, the result of the addition of any combination of values are unique.
Create an enum this way using a function like this. It is very easy to create behaviours on classes, controls or avoid arrays with many values.
In my case, I have an ASCX control with 7 different divs that contain radio buttons, checkboxes with prices, and specific information (and there are a lot of combinations with 7 elements) that must be shown or hidden depending on specific and complex business rules, so I thought that putting an integer value in a member of a Business Entity was a clear and easy way to do it, because in the end you are adding Integer values.
That's all. I hope someone finds it useful.