How to: Create a generic method constraining T to an Enumeration

Although I believe that as part of the .Net framework version 4 you can specify the Enumeration type that you need when you are creating a generic method, this is not available in the .Net framework 3.5 (or in previous releases for that matter). The problem then becomes that you don’t want to have a method that allows any type of object to be passed to it (the main reason why you’re choosing generics right?) so how can you restrict it as much as possible to guarantee you’re getting the enumeration you want?

What I found is that you can restrict the generic type to be of type ‘struct’. This of course is not perfect as it could not only be any kind of enumeration, but it also could be a value type (int, bool, etc.) or a custom structure that uses struct. Further research reveals that Enum implements an interface named ‘IConvertible’ so adding this to the where clause further restricts the object that can be passed to the generic method/class almost guaranteeing an enumeration.

At this point I’m happy but for those who want to take it a step further you can perform a check within the method like the one below as a final gate:

   if (!typeof(T).IsEnum) 
   {
      throw new ArgumentException("T must be an enum type");
   }

This should help you get the job done. Unfortunately at this point you can receive any given enum and not one of a particular type, but again, you can run code similar to the one above and then throw an exception or return a ‘default value’ if it is not what you were expecting. Again, not ideal but it’s the best I have at this point. So what we have thus far looks more or less like this:

public T MyMethod<T>() where T : struct, IConvertible
{
   if (!typeof(T).IsEnum)
   {
      throw new ArgumentException("T must be an enum type");
   }

   //...
}

Hopefully this will do the trick for most.

You may also like...

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: