Странное поведение коммутатора в.NET 4

У меня есть проблема при понимании того, что является причинами ошибка компиляции в коде ниже:

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";
    }
}

Ошибка, которую я получаю, находится в switch (test) строка:

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

Intellisence показывает мне, что операция нечто будет разрешена на времени выполнения, которое прекрасно, потому что я использую динамический тип в качестве параметрического усилителя. Однако я не понимаю как if компиляции условия, прекрасные, когда переключатель не делает.

Код выше является просто упрощенной версией того, что я имею в своем приложении (VSTO), который появился после миграции приложения от VSTO3 до VSTO4, когда один метод в VSTO был изменен на возврат dynamic введите значения вместо object.

Кто-либо может дать мне объяснение, какова проблема. Я знаю, как разрешить его, но я хотел бы понять то, что происходит.

10
задан RaYell 2 June 2010 в 12:54
поделиться

5 ответов

Поскольку вы вызываете метод динамически, результатом также является динамический (поскольку возвращаемое значение может быть чем угодно - оно не знает до времени выполнения). И вы не можете переключить на динамический тип переменной.

10
ответ дан 3 December 2019 в 22:35
поделиться

Тип выражения переключения оценивается компилятором во время компиляции. Тип dynamic оценивается во время выполнения, поэтому компилятор не может проверить, является ли он (или может быть преобразован) одним из разрешенных типов (который, согласно Спецификации языка C # 4 это sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, string или тип перечисления).

3
ответ дан 3 December 2019 в 22:35
поделиться

Это неожиданное поведение - я ожидал, что переменная будет установлена ​​в метод, который явно возвращает строку, чтобы правильно определить тип строки. Ну что ж .....

Если вы замените:

var test = foo (x);

на:

string test = foo (x);

, все будет скомпилировано, как вы знаете .

Это безопасно, поскольку вы объявили foo () как возвращающую строку, и, возможно, в любом случае более интуитивно понятно для чтения в долгосрочной перспективе.

0
ответ дан 3 December 2019 в 22:35
поделиться

Как говорит Мэтт Эллен, но с немного большей предысторией.

Для оператора switch : из Спецификации языка C # v4.0:

Управляющий тип оператора switch устанавливается переключателем выражение.

  • Если тип выражения switch - sbyte , byte , short , ushort , int , uint , long , ulong , bool , char , string или enum-type , или, если это обнуляемый тип, соответствующий одному из этих типов, то это управляющий тип оператора switch .
  • В противном случае должно существовать ровно одно определяемое пользователем неявное преобразование (§6.4) из типа выражения switch в один из следующих возможных управляющих типов: sbyte , byte , короткий , ushort , int , uint , long , ulong , ] char , строка или обнуляемый тип, соответствующий одному из этих типов.
  • В противном случае, если такое неявное преобразование не существует или существует более одного такого неявного преобразования, возникает ошибка времени компиляции.

Для оператора if выражение оценивается как логическая операция. Оценка выражения отложена до времени выполнения из-за использования dynamic в вызове метода в присвоении переменной. Из приведенной выше спецификации похоже, что переключатель требует оценки типов переключателей во время компиляции.

2
ответ дан 3 December 2019 в 22:35
поделиться

Операторы Switch поддерживают только числа, символы, перечисления и строки. dynamic не является ни одной из этих вещей. Если вы предполагаете, что x является строкой, вы можете просто привести его:

dynamic x = ""; 
string test = (string)foo(x); 

Вы просто получите ошибку времени выполнения, если это не так.

0
ответ дан 3 December 2019 в 22:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: