O que causa esse problema?
Parece um bug do compilador para mim. Pelo menos, sim. Embora as expressões decimal.TryParse(v, out a)e decimal.TryParse(v, out b)sejam avaliadas dinamicamente, eu esperava que o compilador ainda entendesse que, no momento em que atinge a <= b, ambos ae bestão definitivamente atribuídos. Mesmo com as estranhezas que você pode descobrir na digitação dinâmica, eu esperaria apenas avaliar a <= bdepois de avaliar ambas as TryParsechamadas.
No entanto, verifica-se que por meio de operador e conversão complicada, é inteiramente viável ter uma expressão A && B && Cque avalia Ae Cmas não B- se você for astuto o suficiente. Veja o relatório de bug de Roslyn para ver o exemplo engenhoso de Neal Gafter.
Fazer isso funcionar dynamicé ainda mais difícil - a semântica envolvida quando os operandos são dinâmicos são mais difíceis de descrever, porque para realizar a resolução de sobrecarga, você precisa avaliar operandos para descobrir quais tipos estão envolvidos, o que pode ser contra-intuitivo. No entanto, novamente Neal veio com um exemplo que mostra que o erro do compilador é necessário ... isso não é um bug, é uma correção de bug . Muitos elogios a Neal por provar isso.
É possível consertá-lo por meio das configurações do compilador?
Não, mas existem alternativas que evitam o erro.
Em primeiro lugar, você pode impedir que seja dinâmico - se você sabe que só usará strings, pode usar IEnumerable<string> ou dar à variável de intervalo vum tipo de string(ou seja from string v in array). Essa seria minha opção preferida.
Se você realmente precisa mantê-lo dinâmico, basta fornecer bum valor para começar:
decimal a, b = 0m;
Isso não fará mal nenhum - sabemos que na verdade sua avaliação dinâmica não fará nada maluco, então você ainda acabará atribuindo um valor a bantes de usá-lo, tornando o valor inicial irrelevante.
Além disso, parece que adicionar parênteses também funciona:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
Isso muda o ponto em que várias peças de resolução de sobrecarga são acionadas e deixa o compilador feliz.
Ainda existe um problema - as regras da especificação sobre atribuição definitiva com o &&operador precisam ser esclarecidas para afirmar que elas só se aplicam quando o &&operador está sendo usado em sua implementação "regular" com dois booloperandos. Vou tentar garantir que isso seja corrigido para o próximo padrão ECMA.
bdepois de atribuí-lo por meio de umoutparâmetro.