Что вызывает эту проблему?
Мне кажется, это ошибка компилятора. По крайней мере, так оно и было. Хотя 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параметр.