Ich habe einige Forschung auf diese durch die Verwendung verschiedener Methoden, um Werte zu einem nullable int zuweisen. Hier ist, was passierte, wenn ich verschiedene Dinge tat. Sollte klären, was los ist. Behalten Sie im Hinterkopf: Nullable<something>
oder die Kurzform something?
ist eine Struktur, für die der Compiler eine Menge Arbeit zu tun scheint, damit wir sie mit null verwenden können, als ob sie eine Klasse wäre.
Wie Sie unten sehen werden, SomeNullable == null
y SomeNullable.HasValue
wird immer ein erwartetes true oder false zurückgeben. Auch wenn dies im Folgenden nicht gezeigt wird, SomeNullable == 3
ist ebenfalls gültig (vorausgesetzt, SomeNullable ist ein int?
).
Während SomeNullable.Value
führt zu einem Laufzeitfehler, wenn wir null
a SomeNullable
. Dies ist in der Tat der einzige Fall, in dem Nullables uns ein Problem bereiten könnten, dank einer Kombination von überladenen Operatoren, überladenen object.Equals(obj)
Methode, Compiler-Optimierung und Affentheater.
Hier ist eine Beschreibung des Codes, den ich ausgeführt habe, und der Ausgabe, die er in Form von Etiketten erzeugt hat:
int? val = null;
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
Ok, versuchen wir die nächste Initialisierungsmethode:
int? val = new int?();
lbl_Val.Text = val.ToString(); //Produced an empty string.
lbl_ValVal.Text = val.Value.ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValEqNull.Text = (val == null).ToString(); //Produced "True" (without the quotes)
lbl_ValNEqNull.Text = (val != null).ToString(); //Produced "False"
lbl_ValHasVal.Text = val.HasValue.ToString(); //Produced "False"
lbl_NValHasVal.Text = (!(val.HasValue)).ToString(); //Produced "True"
lbl_ValValEqNull.Text = (val.Value == null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
lbl_ValValNEqNull.Text = (val.Value != null).ToString(); //Produced a runtime error. ("Nullable object must have a value.")
Alles wie gehabt. Denken Sie daran, dass die Initialisierung mit int? val = new int?(null);
mit der Übergabe von null an den Konstruktor hätte zu einem COMPILE-Zeitfehler geführt, da der WERT des nullbaren Objekts nicht nullbar ist. Nur das Wrapper-Objekt selbst kann gleich null sein.
Ebenso würden wir einen Kompilierzeitfehler von erhalten:
int? val = new int?();
val.Value = null;
ganz zu schweigen davon, dass val.Value
ist sowieso eine schreibgeschützte Eigenschaft, was bedeutet, dass wir nicht einmal so etwas wie verwenden können:
val.Value = 3;
aber auch hier ermöglichen uns polymorphe überladene implizite Konvertierungsoperatoren dies:
val = 3;
Kein Grund zur Sorge über polysomthing whatchamacallits obwohl, so lange es funktioniert richtig? :)
10 Stimmen
Ich habe eine ähnliche Frage gestellt... und einige gute Antworten erhalten: stackoverflow.com/questions/633286/
3 Stimmen
Persönlich würde ich verwenden
HasValue
da ich der Meinung bin, dass Wörter besser lesbar sind als Symbole. Es liegt aber ganz an Ihnen und daran, was zu Ihrem Stil passt.1 Stimmen
.HasValue
macht mehr Sinn, da es bedeutet, dass der Typ vom TypT?
statt eines Typs, der nullbar sein kann, wie z. B. Strings.