Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird switch behavior in .NET 4

I have a problem understanding what's causes the compilation error in the code below:

static class Program
{
    static void Main()
    {
        dynamic x = "";
        var test = foo(x);

        if (test == "test")
        {
            Console.WriteLine(test);
        }

        switch (test)
        {
            case "test":
                Console.WriteLine(test);
                break;
        }
    }

    private static string foo(object item)
    {
        return "bar";
    }
}

The error I get is in switch (test) line:

A switch expression or case label must be a bool, char, string, integral, 
enum, or corresponding nullable type.

Intellisence shows me that foo operation will be resolved on runtime, which is fine because I'm using a dynamic type as a param. However I don't understand how if condition compiles fine when switch doesn't.

Code above is just simplified version of what I have in my application (VSTO) which appeared after migrating the app from VSTO3 to VSTO4 when one method in VSTO was changed to return dynamic type values instead of object.

Can anyone give me an explanation what's the problem. I know how to resolve it but I'd like to understand what's happening.

like image 620
RaYell Avatar asked Jun 02 '10 12:06

RaYell


3 Answers

Because you're calling a method dynamically, the result is also a dynamic (as the return value could be anything - it doesn't know until runtime). And you can't switch on a dynamic variable type.

like image 74
thecoop Avatar answered Sep 27 '22 15:09

thecoop


The type of the switch expression is evaluated by the compiler, at compile time. The type of dynamic is evaluated in runtime, so the compiler cannot verify whether it is (or is convertible to) one of the allowed types (which, according to the C# 4 Language Specification is sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, string, or an enum-type).

like image 21
Fredrik Mörk Avatar answered Sep 27 '22 15:09

Fredrik Mörk


As Matt Ellen says, but with a little more background.

For the switch statement: from the C# Language Specification v4.0:

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, bool, char, string, or an enum-type, or if it is the nullable type corresponding to one of these types, 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, or, a nullable type corresponding to one of those types.
  • Otherwise, if no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.

For the if statement the expression is evaluated as a Boolean operation. The expression evaluation is deferred to run-time because of the use of dynamic in the method call in the variable assignment. From the specification above, it looks like switch requires compile-time evaluation of switch types.

like image 32
dariom Avatar answered Sep 27 '22 16:09

dariom