Snippet: Multi-Valued Enums - Extension Method Style
Omar blogged a method to extract the selected values in an enumeration:
http://blog.omarbesiso.net/index.php/2008/02/13/c-multi-valued-enumerators-flags/
Suppose you had an flags enumeration called Option. You could use his method to write the following code:
Options options = Options.ReadOnly | Options.Archive;
Console.WriteLine("You selected:");
foreach (Options option in EnumHelper.GetSelectedEnumValues<Options>(options))
{
Console.WriteLine(option);
}
While a generic static method is fine, I think this is a good example of where an extension method would make for a more readable solution. Using his method could look like this:
Options options = Options.ReadOnly | Options.Archive;
Console.WriteLine("You selected:");
foreach (Options option in options.Selected())
{
Console.WriteLine(option);
}
Achieving this is very simple. The bold parts were the only changes I made in order to convert the method into an extension method:
static class EnumExtensions
{
public static Collection<T> Selected<T>(this T enumInputValue)
where T : struct
{
Type enumType = typeof(T);
if (!enumType.IsEnum)
{
throw new ArgumentException(enumType.ToString()
+ " is not an Enum.", "T", null);
}
Array enumValues = Enum.GetValues(enumType);
long inputValueLong = Convert.ToInt64(enumInputValue);
Collection<T> enumOutputCollection = new Collection<T>();
foreach (T enumValue in enumValues)
{
long enumValueLong = Convert.ToInt64(enumValue);
if ((enumValueLong & inputValueLong) == enumValueLong
&& enumValueLong != 0)
{
enumOutputCollection.Add(enumValue);
}
}
if (enumOutputCollection.Count == 0 && enumValues.GetLength(0) > 1)
{
T enumNoneValue = (T)enumValues.GetValue(0);
if (Convert.ToInt64(enumNoneValue) == 0)
{
enumOutputCollection.Add(enumNoneValue);
}
}
return enumOutputCollection;
}
}
You could go a step further by "yield return’ing" the items and returning an IEnumerable<T> rather than a Collection<T>, but I don’t expect it would make any difference in reality. Changing the return value to an IEnumerable<T> rather than a Collection<T> is probably a nicer design though.
Sure, extension methods can be abused, but I think this is another case where they makes the intent of the code clearer. That said, I have plenty of examples where I’ve taken them too far
Filed under: C#

I’d love to see some of the examples of how not to use extension methods
I’m not sure if I’d use “Selected()”, but this made me think of an enum extension method that would be handy:
public static bool Contains(this T enumValue)
{
…
}
So if I had a multivalued enum I could simply say:
if (myEnumValue.Contains(MyEnum.OnePossibleValue)) { … }
Much nicer than the “bitwise &” syntax.
Noice.
Good to see alternatives to the type safe enum pattern for encapsulation too.
This just makes me cringe.. whatever happened to using the bitwise operations that are instant? A few dozen machine instructions are now turned into hundreds of complicated function calls.
@John Smith,
Yep, if I found myself doing comparrisons over a billion enums in a scallable system, I might reconsider this method. Otherwise, I tend to favour readability.
Intel still haven’t refunded me for last year’s Unused CPU Cycles declaration.
Paul