Cosa causa questo problema?
A me sembra un bug del compilatore. Almeno, lo ha fatto. Sebbene le espressioni decimal.TryParse(v, out a)e decimal.TryParse(v, out b)vengano valutate dinamicamente, mi aspettavo che il compilatore comprendesse ancora che nel momento in cui raggiunge a <= b, entrambe ae bsono state assegnate definitivamente. Anche con le stranezze che puoi trovare nella digitazione dinamica, mi aspetto di valutare solo a <= bdopo aver valutato entrambe le TryParsechiamate.
Tuttavia, si scopre che attraverso l'operatore e la conversione complicata, è del tutto fattibile avere un'espressione A && B && Cche valuta Ae Cma non B- se sei abbastanza astuto. Vedi il bug report di Roslyn per l'esempio geniale di Neal Gafter.
Fare questo lavoro dynamicè ancora più difficile: la semantica coinvolta quando gli operandi sono dinamici è più difficile da descrivere, perché per eseguire la risoluzione del sovraccarico, è necessario valutare gli operandi per scoprire quali tipi sono coinvolti, il che può essere controintuitivo. Tuttavia, ancora una volta Neal ha escogitato un esempio che mostra che è richiesto l'errore del compilatore ... questo non è un bug, è una correzione di bug . Enormi quantità di complimenti a Neal per averlo dimostrato.
È possibile risolverlo tramite le impostazioni del compilatore?
No, ma ci sono alternative che evitano l'errore.
In primo luogo, potresti impedire che sia dinamico: se sai che utilizzerai solo stringhe, puoi usare IEnumerable<string> o dare alla variabile di intervallo vun tipo di string(cioè from string v in array). Questa sarebbe la mia opzione preferita.
Se hai davvero bisogno di mantenerlo dinamico, dai bun valore per iniziare:
decimal a, b = 0m;
Questo non farà alcun danno: sappiamo che in realtà la tua valutazione dinamica non farà nulla di folle, quindi finirai comunque per assegnare un valore bprima di usarlo, rendendo il valore iniziale irrilevante.
Inoltre, sembra che anche l'aggiunta di parentesi funzioni:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
Ciò cambia il punto in cui vengono attivati vari pezzi di risoluzione del sovraccarico e sembra rendere felice il compilatore.
Resta ancora un problema: le regole della specifica sull'assegnazione definitiva con l' &&operatore devono essere chiarite per affermare che si applicano solo quando l' &&operatore viene utilizzato nella sua implementazione "regolare" con due booloperandi. Cercherò di assicurarmi che questo sia corretto per il prossimo standard ECMA.
bdopo averlo assegnato tramite unoutparametro.