2013-07-14 38 views
5

Załóż program C# z dwiema wartościami dziesiętnymi z wartościami zerowymi A i B. Następujący dodatek zwraca tylko wartość A: var result = A ?? 0 + B ?? 0; Poprawne użycie to: var result = (A? 0) + (B ?? 0);Dodatek C# z wartościami dziesiętnymi z wartościami zerowymi i nadrzędnością ?? operator

Przykładowy program konsoli:

class Program 
{ 
    static void Main(string[] args) 
    { 
     A = (decimal)0.11; 
     B = (decimal)0.69; 

     NullableDecimalAddition(); 

     Console.ReadLine(); 
    } 

    public static decimal? A { get; set; } 
    public static decimal? B { get; set; } 

    private static void NullableDecimalAddition() 
    { 
     decimal result1 = A ?? 0 + B ?? 0; 
     decimal result2 = (A ?? 0) + (B ?? 0); 
     Console.WriteLine("result1: " + result1); // = 0.11 
     Console.WriteLine("result2: " + result2); // = 0.80 
    } 
} 

Moje pytanie brzmi co dzieje się podczas obliczania z wynik1. Jak jest pierwszeństwo + i ?? operatorzy?

Odpowiedz

8

Odpowiedź tinstaafl jest poprawna. Aby go rozwinąć:

Operator ?? to prawy asocjacyjny, a operator + ma wyższy priorytet. Dlatego A ?? 0 + B ?? 0 jest odpowiednikiem A ?? ((0 + B) ?? 0), a nie (A ?? 0) + (B ?? 0).

Dlatego działanie A ?? 0 + B ?? 0 jest:

  • Compute A, którego stan jest typu wartości pustych przecinku. Jeśli ma wartość inną niż NULL, w wyniku otrzymuje wartość dziesiętną. Teraz skończyliśmy; B nigdy nie jest obliczana.
  • Zero zostało już skonwertowane na wartość dziesiętną przez kompilator, a jego zerowa wartość sprawdzająca dla podniesionej arytmetyki jest zniesiona. (Aby uzyskać szczegółowe informacje, patrz my series of articles on how nullable arithmetic is optimized by the compiler).
  • B jest obliczane i sprawdzane pod kątem zerowej wartości. Jeśli jest pusty, wynik dodania jest zerowy; jeśli nie, wynikiem dodania jest dziesiętny z możliwością zerowania.
  • Wynik dodania jest teraz sprawdzany pod kątem wartości NULL. Jeśli jest zerowy, wynikiem jest zero (ponownie, już przeliczone na dziesiętne). Jeśli nie jest null, to jego wartość jest pobierana i staje się wynikiem.

To nie jest zamierzone działanie; możesz uzyskać zamierzoną akcję za pomocą (A ?? 0) + (B ?? 0). Jeśli zamiast tego zamierzałeś użyć "zero", jeśli albo strona ma wartość null ", możesz użyć (A + B) ?? 0. Nawiasy w tym ostatnim są niepotrzebne, ale dobry pomysł, biorąc pod uwagę, że byłeś zdezorientowany co do pierwszeństwa + vs ??.

+0

OK, dziękuję za poprawną odpowiedź – FSou1

+0

Jest genialny, gdy otrzymujemy tego rodzaju informacje. –

+0

Dziękuję wszystkim za odpowiedzi i wyjaśnienia. – Nicolo

2

Bez() w pierwszym stwierdzeniu, mówisz pierwszy? operator zwraca 0 + B, jeśli A jest zerowe, a drugie? operator zwraca wartość 0, jeśli B ma wartość null. dlatego, że operator + jest używany przez ?? operator instrukcja zwróci tylko A. Jeśli ustawisz A na wartość null, powinieneś zwrócić .69

1

Myślę, co ważniejsze, nie powinieneś zostawiać tego interpretacji nikogo, jest to wyraźny przykład, kiedy powinieneś zawsze używać nawiasy dla czytelności i unikania wątpliwości. Konserwacja jest priorytetem.

+1

W rzeczywistości, dodawanie zostaje wykonane najpierw, następnie pierwsze połączenie, a następnie drugie połączenie. Więc "A ?? 0 + B ?? 0' jest równoważne 'A ?? (0 + B)? 0', a nie 'A ?? (0 + B ?? 0) ' –

+0

dzięki, nie wiedziałem o tym, będę edytować mój post, aby zostawić tylko moje zalecenie dotyczące czytelności. –

+0

@RobertHarvey: Twój komentarz jest nieprawidłowy. Null koalescing jest prawostronny, a addycja ma wyższy priorytet, więc 'A ?? 0 + B ?? 0', 'A ?? (0 + B)? 0' i 'A ?? (0 + B ?? 0) 'są równoważne z' A ??((0 + B) ?? 0) '. Rzeczy równoważne z tym samym są z definicji równoważne sobie; to właśnie oznacza "równoważny". –