Что вызывает эту проблему?
Мне кажется, это ошибка компилятора. По крайней мере, так оно и было. Хотя decimal.TryParse(v, out a)
и decimal.TryParse(v, out b)
выражения вычисляются динамически, я ожидал , что компилятор до сих пор понять , что к тому времени он достигает a <= b
, как a
и b
определенно присвоенной. Даже с учетом странностей, которые могут возникнуть при динамической типизации, я бы ожидал, что когда-либо буду оценивать только a <= b
после оценки обоих TryParse
вызовов.
Тем не менее, оказывается, что через оператор и преобразование сложного, это вполне возможно , чтобы иметь выражение , A && B && C
которое приводится A
и , C
но не B
- если вы хитрая достаточно. См. Гениальный пример Нила Гафтера в отчете об ошибке Roslyn .
Заставить эту работу работать dynamic
еще сложнее - семантику, используемую, когда операнды являются динамическими, сложнее описать, потому что для выполнения разрешения перегрузки вам необходимо оценить операнды, чтобы выяснить, какие типы задействованы, что может быть нелогичным. Однако, опять - таки Нил придумал пример , который показывает , что требуется ошибка компилятора ... Это не ошибка, это ошибка исправления . Большое спасибо Нилу за доказательство этого.
Можно ли исправить через настройки компилятора?
Нет, но есть альтернативы, позволяющие избежать ошибки.
Во-первых, вы можете сделать так, чтобы он не был динамическим - если вы знаете, что будете использовать только строки, вы можете использовать IEnumerable<string>
или дать переменной диапазона v
тип string
(т.е. from string v in array
). Это был бы мой предпочтительный вариант.
Если вам действительно нужно сохранить динамику, просто укажите b
значение для начала:
decimal a, b = 0m;
Это не принесет никакого вреда - мы знаем, что на самом деле ваша динамическая оценка не сделает ничего сумасшедшего, поэтому вы все равно будете присваивать значение, b
прежде чем использовать его, делая начальное значение несущественным.
Вдобавок кажется, что добавление круглых скобок тоже работает:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
Это меняет точку, в которой запускаются различные части разрешения перегрузки, и делает компилятор счастливым.
Остается еще одна проблема - &&
необходимо уточнить правила спецификации по определенному назначению с оператором, чтобы указать, что они применяются только тогда, когда &&
оператор используется в его «обычной» реализации с двумя bool
операндами. Я постараюсь исправить это для следующего стандарта ECMA.
b
после его назначения черезout
параметр.