2010-01-28 18 views

Odpowiedz

10

Podane jest to w specyfikacji dla podniesionych operatorów binarnych. Z §7.2.7:

dla operatorów binarnych

+ - */% & |^<< >>

podniesionym forma operatora występuje wówczas typy argumentów i rezultatu są wszystkie typy wartości bez pustych. Uniesiona forma jest konstruowana przez dodanie pojedynczego modyfikatora ? do każdego argumentu i typu wyniku. Podniesiony operator daje wartość pustą, jeśli jeden lub oba operandy mają wartość null (wyjątek to & i | operatory typu bool ?, jak opisano w §7.10.3). W przeciwnym razie operator podniesiony rozpakuje operandy, zastosuje operator bazowy i opakuje wynik.

Rozumowanie jest takie: jesteś myśleć o null o wartości pustych typu, co oznacza „nie wiem, co jest wartością”. Jaki jest wynik "nie wiem" plus jeden? "Nie wiem." Dlatego wynik powinien być następujący: null.

+0

Twoja logika jest dobrze sformułowana, ale naprawdę powinna rzucić wyjątek. Pomyśl o + jako o syntaktycznie prostszym sposobie działania number.Plus (2). Powinien zdecydowanie rzucić wyjątek, jeśli liczba jest zerowa lub może łatwo spowodować nieoczekiwane zachowanie. –

+0

Co gorsza, jeśli masz numer i dodasz do niego wartość zerową, stanie się on zerowy. –

0

Niestety tak nie jest. Xma wartość zerową jak w pierwszym wierszu, więc dodajesz 1 do wartości null, co równa się zeru.

Jak to int pustych, można użyć x.HasValue aby sprawdzić, czy to ma jakąś wartość, a następnie x.Value aby uzyskać rzeczywistą wartość int z

2

Dlaczego można oczekiwać kompilator do oddania go jako int, kiedy ogłosiłeś to jako Nullable? Kompilator robi to, co mu kazano, i null +1 = null.

Musisz odrzucić jawnie lub sprawdzić x.HasValue przed próbą dodania int.

5

Nullable nigdy nie są właściwie zerowymi odniesieniami. Są to zawsze odniesienia do obiektów. Ich klasy wewnętrzne zastępują operatory == i =. Jeśli zostaną porównane z wartością null, zwrócą wartość właściwości HasValue.

+1

Pierwsze zdanie jest poprawne. Dwa środkowe zdania są nieprawidłowe. Nullable są * nigdy * odniesieniami do obiektów. Struktura Nullable ma * nie * przesłania operatorowi równości. Nie ma czegoś takiego jak przesłonięcie operatora przypisania. Ostatnie zdanie jest poprawne. –

+0

Masz rację - nie operator przypisania, ale niejawna konwersja z int. Są zdecydowanie różnymi operatorami, ale efekt jest taki sam. Dziękuję za wskazanie tego. – rusty

2

Powodem tego jest to, że kompilator tworzy „podnoszony” operatora dla pustych typów - w tym przypadku jest to coś w rodzaju:

public static int? operator +(int? a, int? b) 
{ 
    return (a == null || b == null) ? (int?)null : a.Value + b.Value 
} 

myślę, że jeśli spróbujesz przypisać wynik nie- wartość zerowa, kompilator będzie zmuszony użyć nie-nullable overload i przekonwertować x na int.

e.g. int i = x + 1; //throws runtime exception 
+0

faktycznie int i = x + 1 jest błędem. int i = (int) (x + 1) wygeneruje wyjątek, jeśli x nie ma wartości. – Dolphin

0

Niezależnie od tego, czy x faktycznie nigdy nie jest pusta, to nawet nie o to chodzi.

Chodzi o to, czy kiedykolwiek widziałeś NullReferenceException podczas próby dodania?

Poniższy przykład nie rzuca NullReferenceException i jest całkowicie poprawny.

string hello = null; 
string world = "world"; 
string hw = hello+world; 

co można uzyskać tylko NullReferenceException jeśli próbujesz uzyskać dostęp do elementu na obiekcie, który ma wartość null.

-1

int? nigdy nie może być wartością null, ponieważ jest to struktura. Struktury żyją na stosie, a stos nie radzi sobie dobrze z wartością zerową.

Zobacz What is a NullPointerException, and how do I fix it?

Również dopuszczające wartość null typy mają 2 bardzo użytecznych właściwości: hasValue, Value

ten kod:

 if (x != null) 
     { 
      return (int) x; 
     } 

Powinny być refactored do tego:

 if (x.HasValue) 
     { 
      return x.Value; 
     } 
+0

To jest całkowicie nieprawidłowe. Po pierwsze, typy wartości nie "żyją na stosie". Typy wartości są aktywne niezależnie od tego, gdzie mieszkają, na stosie lub stercie, jak uważa menedżer pamięci. Po drugie, całkowicie legalne jest posiadanie referencji zerowej na stosie. "string s = null;", na stosie jest zerowa referencja, nie ma problemu. –

+1

Doceniam korektę. Kiedy zaczynałem w .NET, pamiętam: DateTime x = null; i otrzymanie tego błędu "Kompilator nie może przypisać wartości null do typu wartości, null może zostać przypisany tylko do typu referencji. struct to typ wartości." Źle zrozumiałem przesłanie. Błąd mówi o ograniczeniach typu null-literalnego, a nie typu wartości. Dzięki za zasłużone uderzenie w głowę. – fremis

Powiązane problemy