Just wanted to share a helper class I’m using in some projects to make it easier to work with enums.
public static class EnumHelpers
{
private const string MustBeAnEnumeratedType = @"T must be an enumerated type";
public static T ToEnum<T>(this string s) where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new ArgumentException(MustBeAnEnumeratedType);
T @enum;
Enum.TryParse(s, out @enum);
return @enum;
}
public static T ToEnum<T>(this int i) where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new ArgumentException(MustBeAnEnumeratedType);
return (T) Enum.ToObject(typeof (T), i);
}
public static T[] ToEnum<T>(this int[] value) where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new ArgumentException(MustBeAnEnumeratedType);
var result = new T[value.Length];
for (int i = 0; i < value.Length; i++)
result[i] = value[i].ToEnum<T>();
return result;
}
public static T[] ToEnum<T>(this string[] value) where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new ArgumentException(MustBeAnEnumeratedType);
var result = new T[value.Length];
for (int i = 0; i < value.Length; i++)
result[i] = value[i].ToEnum<T>();
return result;
}
public static IEnumerable<T> ToEnumFlags<T>(this int i) where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new ArgumentException(MustBeAnEnumeratedType);
return
(from flagIterator in Enum.GetValues(typeof (T)).Cast<int>()
where (i & flagIterator) != 0
select ToEnum<T>(flagIterator));
}
public static bool CheckFlag<T>(this Enum value, T flag) where T : struct, IConvertible
{
if (!typeof(T).IsEnum) throw new ArgumentException(MustBeAnEnumeratedType);
return (Convert.ToInt32(value, CultureInfo.InvariantCulture) & Convert.ToInt32(flag, CultureInfo.InvariantCulture)) != 0;
}
public static IDictionary<string, T> EnumToDictionary<T>() where T : struct, IConvertible
{
if (!typeof (T).IsEnum) throw new ArgumentException(MustBeAnEnumeratedType);
IDictionary<string, T> list = new Dictionary<string, T>();
Enum.GetNames(typeof (T)).ToList().ForEach(name => list.Add(name, name.ToEnum<T>()));
return list;
}
The first ToEnum extension allows you to write something like this:
"Value1".ToEnum<MyEnum>()
It adds a ToEnum method to the string class in order to convert a string to an enum value.
The second ToEnum extension does the same but with ints e.g.:
0.ToEnum<MyEnum>()
The third ToEnum extension is similar but extends int arrays to return a collection of enum values e.g.:
new[] {1, 0}.ToEnum<MyEnum>()
The forth ToEnum extension does the same but with string arrays e.g.:
new[] {"Value2", "Value1"}.ToEnum<MyEnum>()
The ToEnumFlags extension returns a list of enum values when working with flags e.g.:
13.ToEnumFlags<MyEnum2>().Select(e => e.ToString()).Aggregate((e, f) => (e + " " + f))
The EnumToDictionary method returns a dictionary with the enum item name as key and values e.g.:
EnumHelpers.EnumToDictionary<MyEnum>()["Value2"]
The CheckFlag extension converts checks whether an enum flag is set e.g.:
(MyEnum2.Flag1 | MyEnum2.Flag4).CheckFlag(MyEnum2.Flag4)
To test this you can use the following:
internal enum MyEnum
{
Value1,
Value2,
}
[Flags]
internal enum MyEnum2
{
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 8,
}
public static class MainClass
{
public static void Main()
{
Console.WriteLine("1) {0}", (int) "Value1".ToEnum<MyEnum>());
Console.WriteLine("2) {0}", 0.ToEnum<MyEnum>());
Console.WriteLine("3) {0}", new[] {1, 0}.ToEnum<MyEnum>());
Console.WriteLine("4) {0}", new[] {"Value2", "Value1"}.ToEnum<MyEnum>());
Console.WriteLine("5) {0}", 13.ToEnumFlags<MyEnum2>().Select(e => e.ToString()).Aggregate((e, f) => (e + " " + f)));
Console.WriteLine("6) {0}", (int) EnumHelpers.EnumToDictionary<MyEnum>()["Value2"]);
Console.WriteLine("7) {0}", (MyEnum2.Flag1 | MyEnum2.Flag4).CheckFlag(MyEnum2.Flag4));
Console.WriteLine("8) {0}", (MyEnum2.Flag1 | MyEnum2.Flag4).CheckFlag(MyEnum2.Flag3));
}
}
which will output:
1) 0
2) Value1
3) Playground.MyEnum[]
4) Playground.MyEnum[]
5) Flag1 Flag3 Flag4
6) 1
7) True
8) False
I guess most methods are pretty basic but sometimes it’s easier to just have a helper class and not have to think about how to solve the problem again and again (even though it’s not a very complex problem)…