Co powoduje ten problem?
Wydaje mi się, że to błąd kompilatora. A przynajmniej tak. Chociaż wyrażenia decimal.TryParse(v, out a)
i decimal.TryParse(v, out b)
są obliczane dynamicznie, spodziewałem się, że kompilator nadal zrozumie, że zanim dotrze a <= b
, oba a
i b
zostaną ostatecznie przypisane. Nawet z dziwactwami, które możesz wymyślić podczas dynamicznego pisania, spodziewałbym się, że kiedykolwiek ocenię tylko a <= b
po ocenie obu TryParse
wywołań.
Jednak okazuje się, że za pośrednictwem operatora i nawrócenia trudne, jest to całkowicie możliwe, aby mieć wyraz A && B && C
która ocenia A
i C
, ale nie B
- Jeśli jesteś przebiegły dość. Zobacz raport o błędzie Roslyn, aby zapoznać się z genialnym przykładem Neala Gaftera.
Wykonanie tej pracy dynamic
jest jeszcze trudniejsze - semantyka stosowana, gdy operandy są dynamiczne, jest trudniejsza do opisania, ponieważ aby wykonać rozwiązanie przeciążenia, musisz ocenić operandy, aby dowiedzieć się, jakie typy są zaangażowane, co może być sprzeczne z intuicją. Jednak ponownie Neal wymyślił przykład, który pokazuje, że błąd kompilatora jest wymagany ... to nie jest błąd, to naprawa błędu . Ogromne uznanie dla Neala za udowodnienie tego.
Czy można to naprawić poprzez ustawienia kompilatora?
Nie, ale istnieją alternatywy, które pozwalają uniknąć błędu.
Po pierwsze, możesz zatrzymać dynamikę - jeśli wiesz, że będziesz używać tylko łańcuchów, możesz użyć IEnumerable<string>
lub nadać zmiennej zakresu v
typ string
(tj from string v in array
.). To byłaby moja preferowana opcja.
Jeśli naprawdę chcesz zachować dynamikę, po prostu podaj b
wartość na początek:
decimal a, b = 0m;
To nie zaszkodzi - wiemy, że tak naprawdę twoja dynamiczna ocena nie zrobi nic szalonego, więc nadal będziesz przypisywać wartość b
przed jej użyciem, sprawiając, że początkowa wartość będzie nieistotna.
Dodatkowo wydaje się, że dodawanie nawiasów też działa:
where decimal.TryParse(v, out a) && (decimal.TryParse("15", out b) && a <= b)
To zmienia punkt, w którym wyzwalane są różne elementy rozwiązania przeciążenia, i sprawia, że kompilator jest zadowolony.
Pozostaje jeszcze jedna kwestia - zasady specyfikacji dotyczące określonego przypisania do &&
operatora muszą zostać wyjaśnione, aby stwierdzić, że mają one zastosowanie tylko wtedy, gdy &&
operator jest używany w jego „zwykłej” implementacji z dwoma bool
operandami. Spróbuję się upewnić, że zostanie to naprawione dla następnego standardu ECMA.
b
po przypisaniu go za pomocąout
parametru.