views:

698

answers:

8

As in this example:

switch ( myObj.GetType ( ) )
{
    case typeof(MyObject):
     Console.WriteLine ( "MyObject is here" );
     break;
}
+2  A: 

It's that typeof is not a constant and cases must be constants.

L. Moser
Can anyone tell me why this is being voted down instead of just doing it????
L. Moser
Sorry, I fumbled that one. Voted down when I meant to vote up, got distracted (was distracted in the first place), and now it's saying that I can't change it.
jthg
If he edits his answer, I think you can change it.
Philip Wallace
+2  A: 

a switch in C# only works for integrals or strings. myObj.GetType() returns a Type, which is neither an integral or a string.

nos
+6  A: 

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."

Dan Diplo
+10  A: 

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.

Marc Gravell
Thanks Marc. If they handled strings using a Dictionary, why didn't MS do the same for other types by using a Dictionary?
Joan Venge
vb.net allows anything in the switch however
Pondidum
@joan because it only works for compile time constants (such as string litterals). The key is used in the IL code and hence needs to be known at compile time
Rune FS
A: 

Why don't you just tostring() it?

C Bauer
Read Marcs answer...
Philip Wallace
+4  A: 

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: ...
}
Tim Ridgely
A: 

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).

Kyle Trauberman
How can this work, because the value is still not known at compile time!
Philip Wallace
@Philip: The `case` values *are* known at compile time, because they're hardcoded as strings in this case. It's not an optimal solution, but it does work.
Daniel Pryden
+9  A: 

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.

Eric Lippert
Thanks Eric, a good answer. Someone here said vb.net can do this. How does it work? Is it a compromise on vb.net performance or just a different construct than the C# switch statement?
Joan Venge
The documentation for the VB construct is here: http://msdn.microsoft.com/en-us/library/cy37t14y.aspx
Eric Lippert
Thanks Eric, just assumed the poster here was correct. I understand it now.
Joan Venge