Seeing as C# can't switch on a Type (which I gather wasn't added as a special case because is-a relationships mean that more than one distinct case might apply), is there a better way to simulate switching on type than this?
void Foo(object o)
{
if (o is A)
{
((A)o).Hop();
}
else if (o is B)
{
((B)o).Skip();
}
else
{
throw new ArgumentException("Unexpected type: " + o.GetType());
}
}
Switching on types is definitely lacking in C# (UPDATE: in C#7 / VS 2017 switching on types is supported - see Zachary Yates's answer below). In order to do this without a large if/else if/else statement, you'll need to work with a different structure. I wrote a blog post awhile back detailing how to build a TypeSwitch structure.
http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx
Short version: TypeSwitch is designed to prevent redundant casting and give a syntax that is similar to a normal switch/case statement. For example, here is TypeSwitch in action on a standard Windows form event
The code for TypeSwitch is actually pretty small and can easily be put into your project.
I such cases I usually end up with a list of predicates and actions. Something along these lines:
I use
For built-in types, you can use the TypeCode enumeration. Please note that GetType() is kind of slow, but probably not relevant in most situations.
For custom types, you can create your own enumeration, and either an interface or a base class with abstract property or method...
Abstract class implementation of property
Abstract class implementation of method
Interface implementation of property
Interface implementation of method
One of my coworkers just told me about this too: This has the advantage that you can use it for literally any type of object, not just ones that you define. It has the disadvantage of being a bit larger and slower.
First define a static class like this:
And then you can use it like this:
Given inheritance facilitates an object to be recognized as more than one type, I think a switch could lead to bad ambiguity. For example:
Case 1
Case 2
Because s is a string and an object. I think when you write a
switch(foo)
you expect foo to match one and only one of thecase
statements. With a switch on types, the order in which you write your case statements could possibly change the result of the whole switch statement. I think that would be wrong.You could think of a compiler-check on the types of a "typeswitch" statement, checking that the enumerated types do not inherit from each other. That doesn't exist though.
foo is T
is not the same asfoo.GetType() == typeof(T)
!!I would create an interface with whatever name and method name that would make sense for your switch, let's call them respectively: IDoable that tells to implement void Do().
and change the method as follows:
At least with that you are safe at the compilation-time and I suspect that performance-wise it's better than checking type at runtime.