Ответ 1
Поскольку вы вызываете метод динамически, результатом также является dynamic
(поскольку возвращаемое значение может быть любым - оно не известно до выполнения). И вы не можете switch
по типу переменной dynamic
.
У меня возникла проблема с пониманием того, что вызывает ошибку компиляции в коде ниже:
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 показывает мне, что операция foo будет разрешена во время выполнения, что отлично, потому что я использую динамический тип в качестве параметра. Однако я не понимаю, как условие if
компилируется нормально, когда переключатель не работает.
Код выше - это просто упрощенная версия того, что у меня есть в приложении (VSTO), которое появилось после переноса приложения из VSTO3 в VSTO4, когда один метод в VSTO был изменен, чтобы возвращать значения типа dynamic
вместо object
.
Может ли кто-нибудь дать мне объяснение, в чем проблема. Я знаю, как это решить, но я хотел бы понять, что происходит.
Поскольку вы вызываете метод динамически, результатом также является dynamic
(поскольку возвращаемое значение может быть любым - оно не известно до выполнения). И вы не можете switch
по типу переменной dynamic
.
Тип выражения switch вычисляется компилятором во время компиляции. Тип dynamic
оценивается во время выполнения, поэтому компилятор не может проверить, является ли он (или конвертируется) одним из разрешенных типов (который, согласно Спецификация языка С# 4 - это sbyte, byte, short, ushort, int, uint, long, ulong, bool, char, string или enum-type).
Как говорит Мэтт Эллен, но немного больше фона.
Для оператора switch
: из спецификации языка С# v4.0:
Тип управляющий тип оператора switch
устанавливается выражением switch.
sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, bool
, char
, string
или enum-type, или если это тип с нулевым значением, соответствующий одному из этих типов, то это управляющий тип оператора switch
.sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, string
или тип с нулевым значением, соответствующий одному из этих типов.Для оператора if
выражение оценивается как операция Boolean. Оценка выражения отложена на время выполнения из-за использования dynamic
в вызове метода в присваивании переменной. Из вышеприведенной спецификации выглядит, что switch
требует оценки времени переключения типов коммутатора.
Это неожиданное поведение - я бы ожидал, что переменная var задана методом, который явно возвращает строку для правильного вывода строкового типа. О, хорошо.....
Если вы замените:
var test = foo (x);
с:
string test = foo (x);
все компилируется, как вы знаете.
Это безопасно, поскольку вы объявили foo() как возвращающую строку и, возможно, немного более интуитивно понятным для чтения в долгосрочной перспективе.
Операторы switch поддерживают только номера, символы, перечисления и строки. dynamic
- ничто из этого. Если вы считаете, что x
- это строка, вы можете просто ее перевести:
dynamic x = "";
string test = (string)foo(x);
Вы просто получите ошибку времени выполнения, если это не так.