Ich habe die in C # 6 hinzugefügte Funktion für die sichere Navigation mit etwas Interesse verfolgt. Ich habe mich schon eine Weile darauf gefreut. Aber ich finde ein anderes Verhalten als ich erwartet hatte. Ich verstehe, dass ich wirklich nicht verstehe, wie es wirklich funktioniert.
Angesichts dieser Klasse
class Foo {
public int? Measure;
}
Hier ist ein Code, der den neuen Operator verwendet.
Foo f = new Foo { Measure = 3 };
Console.WriteLine(f?.Measure); // 3
f = new Foo { Measure = null };
Console.WriteLine(f?.Measure); // null
f = null;
Console.WriteLine(f?.Measure); // null
Bis hier funktioniert alles wie erwartet. ?.
greift auf Mitglieder zu, wenn die linke Seite nicht null ist, andernfalls wird null zurückgegeben. Aber hier geht es in eine Richtung, die ich nicht erwartet hatte.
var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null
Was?
Warum kann ich HasValue
von i
erhalten, aber nicht aus demselben Ausdruck, den ich i
zugewiesen habe? Wie kann HasValue
jemals null sein?
Edit: Meine eigentliche Frage bezieht sich auf das Programmverhalten und nicht auf einen Kompilierungsfehler. Ich entfernte die zusätzlichen Informationen über die Kompilierung und konzentrierte mich genauer auf die Frage, warum zwei unterschiedliche Ergebnisse von der gleichen Logik zurückgegeben werden.
Gehen wir das logisch durch.
var f = ???;
var i = f?.Measure;
var t = i.HasValue;
Wir wissen nicht, ob f
null ist oder nicht.
f
ist null, dann ist das Ergebnis (i
) null
f
ist nicht null, dann ist das Ergebnis (i
) eine int
Daher ist i
als int?
definiert und t
ist eine bool
Gehen wir nun durch:
var f = ???;
var i = f?.Measure.HasValue;
f
is null ist, ist das Ergebnis (i
) null f
ist nicht null, ist das Ergebnis (i
) Measure.HasValue
, was ein Bool ist. Daher ist i
ein bool?
.
Wenn f
null ist, schließen wir kurz und geben null zurück. Ist dies nicht der Fall, geben wir das bool
-Ergebnis von .HasValue
zurück.
Bei der Verwendung von ?.
- der Rückgabetyp muss ein Referenzwert oder ein Nullable<T>
sein, da der Ausdruck einen Kurzschluss zur Rückgabe von Null bilden kann.
Nullable<T>
ist eigentlich eine Struktur und kann daher nicht null sein, nur seine Value
kann, also HasValue
immer erreichbar sein.
var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null
In diesem Fall ist f null.
i.HasValue
hat false
zurückgegeben, weil i
vom Typ Nullable<int>
ist. Auch wenn der Wert von i
wie in diesem Fall null ist, ist i.HasValue
weiterhin verfügbar.
f?.Measure.HasValue
gibt jedoch sofort null
zurück, nachdem f?
ausgewertet wurde. Daher das Ergebnis, das Sie oben sehen.
Nur um zu zitieren Robs Kommentar :
Die Hauptsache zu erkennen ist, dass Sie lesen und verstehen this: f? .Measure.HasValue wie folgt: (f? .Measure) .HasValue. nicht.