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