2010-01-28 5 views

Antwort

10

Dies ist nach der Spezifikation für aufgehobene binäre Operatoren. Von §7.2.7:

Für die binären Operatoren

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

eine erweiterte Form eines Bedieners, wenn die Operanden und Ergebnis existiert Typen für alle Nicht-Nullable-Wertetypen sind. Die abgehobene Form wird konstruiert, indem jedem Operanden und Ergebnistyp ein einziger ? Modifikator hinzugefügt wird. Der aufgehobene Operator erzeugt einen Nullwert, wenn einer oder beide Operanden null sind (eine Ausnahme sind die & und | Operatoren des bool? -Typs, wie in §7.10.3 beschrieben). Andernfalls entpackt der gehobene Operator die Operanden, wendet den zugrunde liegenden Operator an und umschließt das Ergebnis.

Die Argumentation ist dies: Sie null für eine Nullable Type zu denken, sind im Sinne von „Ich weiß nicht, was der Wert ist.“ Was ist das Ergebnis von "Ich weiß nicht" plus eins? "Ich weiß es nicht." Daher sollte das Ergebnis null lauten.

+0

Ihre Logik ist gut formuliert, aber es sollte wirklich eine Ausnahme auslösen. Denken Sie an + als nur syntaktisch kühlere Art, Nummer zu laufen.Plus (2). Es sollte definitiv eine Ausnahme auslösen, wenn die Zahl null ist oder leicht zu unerwartetem Verhalten führen kann. –

+0

Noch schlimmer, wenn Sie eine Nummer haben und Null hinzufügen, wird es null. –

0

Leider nicht. Die X in x = X + 1 ist Null wie in der ersten Zeile, so dass Sie 1 zu Null hinzufügen, was gleich null ist.

Da es ein Nullable-int ist, können Sie x.HasValue verwenden zu überprüfen, ob es einen Wert hat, und x.Value dann den tatsächlichen Wert int raus

2

Warum würden Sie erwarten, dass die Compiler es zu werfen als int, wenn Sie es als Nullable deklariert haben? Der Compiler tut, was Sie ihm gesagt haben, und null +1 = null.

Sie müssen explizit casten oder x.HasValue überprüfen, bevor Sie versuchen, einen int hinzuzufügen.

5

Nullwerte sind niemals Null-Referenzen. Sie sind immer Objektreferenzen. Ihre internen Klassen überschreiben die Operatoren == und =. Wenn sie mit null verglichen werden, geben sie den Wert der Eigenschaft HasValue zurück.

+1

Der erste Satz ist richtig. Die mittleren zwei Sätze sind falsch. Nullables sind * nie * Objektreferenzen. Die Nullable-Struktur * überschreibt den Gleichheitsoperator * nicht *. Es gibt kein Überschreiben des Zuweisungsoperators. Der letzte Satz ist richtig. –

+0

Sie haben Recht - nicht der Zuweisungsoperator, sondern die implizite Konvertierung von einem int. Sie sind definitiv verschiedene Operatoren, aber am Ende ist der Effekt der gleiche. Danke, dass du darauf hingewiesen hast. – rusty

2

Der Grund dafür ist, dass der Compiler einen ‚angehoben‘ Operator für Nullable Types erzeugt - in diesem Fall ist es so etwas wie:

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

Ich denke, wenn Sie versuchen, das Ergebnis zu einem nicht zuweisen Nullable-Wert, der Compiler wird gezwungen, die Nicht-Nullable-Überladung zu verwenden und x zu einem Int zu konvertieren.

+0

tatsächlich int i = x + 1 ist ein Fehler. int i = (int) (x + 1) löst eine Ausnahme aus, wenn x keinen Wert hat. – Dolphin

0

Egal ob x ist eigentlich nie Null, das ist nicht einmal der Punkt.

Der Punkt ist, wann haben Sie jemals eine NullReferenceException beim Versuch, eine Addition durchzuführen gesehen? Das folgende Beispiel wirft keine NullReferenceException entweder und ist perfekt gültig.

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

würden Sie bekommen nur eine NullReferenceException wenn Sie versuchen, auf ein Objekt ein Element zuzugreifen, die null ist.

-1

int? kann niemals null sein, weil es eine Struktur ist. Strukte leben auf dem Stapel und der Stapel behandelt NULL nicht gut.

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

Auch die Nullable-Typen haben zwei sehr nützliche Eigenschaften: HasValue, Wert

Dieser Code:

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

Sollte auf diese Refactoring:

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

Dies ist völlig inkorrekt. Erstens, Werttypen "leben nicht auf dem Stapel". Werttypen leben unabhängig davon, wo sie leben, entweder im Stack oder im Heap, wie der Speichermanager es für richtig hält. Zweitens ist es vollkommen legal, einen Nullbezug auf dem Stapel zu haben. "String s = null;", es gibt einen Null-Verweis auf dem Stack, kein Problem. –

+1

Ich schätze die Korrektur. Als ich in .NET anfing, erinnere ich mich daran: DateTime x = null; und diesen Fehler erhalten "Der Compiler kann einem Werttyp keinen Nullwert zuweisen; null kann nur einem Referenztyp zugewiesen werden. struct ist ein Werttyp." Ich habe die Nachricht missverstanden. Der Fehler bezieht sich auf die Einschränkungen des Null-Literals und nicht auf den Werttyp. Danke für den wohlverdienten Schlag in den Kopf. – fremis

Verwandte Themen