Enums Multivaluables






2.86/5 (18 votes)
This article describes how to pass more than one value of an enum in a single variable or call
Introduction
Working with enum
s 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.
//Example of BindingFlags Enums
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 enum
s 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 enum
s 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.
// Examples of Enums that can be used as Multivaluables
/// <summary>
/// Integer Enum, whose values are 2^n.
/// </summary>
public enum PlanesTypes
{
NoPlane = 0, //000000
F15_Eagle = 1, //000001
F18A_Hornet = 2, //000010
F14 = 4, //000100
MIG29_Fulcrum = 8, //001000
F16_Falcon = 16, //010000
F127_Phantom = 32 //100000
}
/// <summary>
/// Integer Enum, whose values are 2^n.
/// </summary>
public enum DaysOfWeek
{
NoDay = 0, //0000000
Monday = 1, //0000001
Tuesday = 2, //0000010
Wednesday = 4, //0000100
Thursday = 8, //0001000
Friday = 16, //0010000
Saturday = 32, //0100000
Sunday = 64 //1000000
}
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.
// You can Pass to a method one or more Values as a single Parameter
// Here a logical sum is being done when the | operator is used
//Thursday + Wednesday + Monday + NoDay
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
/// <summary>
/// Summary description for EnumReader.
/// </summary>
public class EnumReader
{
/// <summary>
/// This Method transform Transforms the Multivalue value of an enum in an
/// ArrayList that contains
/// the singles values.
/// </summary>
/// <param name="EnumType">Type of the Enum</param>
/// <param name="EnumValue">Multivalue value of the Enum</param>
/// <returns>ArrayList with as many elements as Values contained
/// in the Multivalue</returns>
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;
}
/// <summary>
/// Implements IComparer to Sort in a Reverse Order.
/// From the Bigger to the Smaller of the Values.
/// </summary>
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 div
s 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.