As in this example:
switch ( myObj.GetType ( ) )
{
case typeof(MyObject):
Console.WriteLine ( "MyObject is here" );
break;
}
As in this example:
switch ( myObj.GetType ( ) )
{
case typeof(MyObject):
Console.WriteLine ( "MyObject is here" );
break;
}
a switch in C# only works for integrals or strings. myObj.GetType() returns a Type, which is neither an integral or a string.
There's a good blog post on MSDN by Peter Hallam which explains the problems of switching on non-constant values.
"The order of the case labels becomes significant in determining which block of code gets executed. Because the case label expressions are not constant the compiler cannot verify that the values of the case labels are distinct, so this is a possibility which must be catered to. This runs counter to most programmers’ intuition about the switch statement in a couple of ways. Most programmers would be surprised to learn that changing the order of their case blocks changed the meaning of their program. To turn it around, it would be surprising if the expression being switched on was equal to an expression in a case label, but control didn’t go to that label."
The problem is that switch
(per the spec) only works with primitives (int etc) and strings. But yes, it would be nice to have F#-style matching.
From §8.7.2:
switch-label: case constant-expression : default :
... The governing type of a switch statement is established by the switch expression. If the type of the switch expression is sbyte, byte, short, ushort, int, uint, long, ulong, char, string, or an enum-type, then that is the governing type of the switch statement. Otherwise, exactly one user-defined implicit conversion (§6.4) must exist from the type of the switch expression to one of the following possible governing types: sbyte, byte, short, ushort, int, uint, long, ulong, char, string. If no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.
It is obvious, however, that working with such a restricted set allows for simple (and efficient) IL. Note that string
is handled via a dictionary map to an integer.
Second on Peter Hallam's post; it's a great explanation.
You can use TypeCode to work with simple types, though.
switch (Type.GetTypeCode(myObj.GetType())) {
case TypeCode.Boolean: ...
case TypeCode.Char: ...
case TypeCode.String: ...
case TypeCode.Object: ...
default: ...
}
You could do
switch ( myObj.GetType().Name )
{
case "MyObject":
Console.WriteLine ( "MyObject is here" );
break;
}
This works because switching only works on primitive types (as others have said).
I would add to Peter's excellent analysis the following thought:
Fundamenatally, the purpose of a "switch" is to choose one of some number of distinct possibilities. A given value of enum, integer, Boolean or string type can only be one value, so it makes sense to "switch" on such a value. But types are fundamentally different. A given value usually has many types. Types frequently overlap. The proposed "type switch" does not match the stated purpose of the switch construct.