C# Switching on Types

Have you ever wanted to do this?

Type t = typeof(int);

switch (t) {
   case typeof(int):
      Console.WriteLine("int!");
      break;
   case typeof(string):
      Console.WriteLine("string!");
      break;
   default:
      Console.WriteLine("unknown!");
      break;
}

Doesn’t work, right?  Throws ‘A value of an integral type expected’.  This is because C# switch statement is picky when it evaluates the cases. It wants static values and can’t get fancy with object comparisons.  Switch statements aren’t just a bunch of if/else statements when boiled down to IL.  There is more detail in this StackOverflow question.

So we’re out of luck, right?  Not so fast.  Let’s think about what we want: behavior associated with a .NET type.  How can we accomplish that?  I got an idea from Judah’s answer to the aforementioned SO question.  Judah uses a generic dictionary to associate the actual type, as the key, with a string.   Interesting.  Why not associate behavior with those types instead?  With delegates like Action<T> and Func<T>, we can do that.

Here is Judah’s answer refactored to use a generic dictionary:

Type someType = typeof(int);

Dictionary<Type, Func<string>> typeTable = new Dictionary<Type, Func<string>>();
typeTable.Add(typeof(string), () => { return "It's a string!"; });
typeTable.Add(typeof(int), () => { return "It's an int!"; });

Console.Write(typeTable[someType].Invoke());

Now we can call any of a number of associated delegates based on a Type object. We can get even fancier if we want, using Action<T> if we don’t need a return value or Func<T, TResult> if we want to pass parameters into the behavior. We get the usual performance hit of using delegates, but unless you’re guiding a missile in real time I don’t think it’s a dealbreaker.

I’ve used this technique and it works great for me, hope you find it useful as well.


Follow

Get every new post delivered to your Inbox.