wake-up-neo.net

C # Sicherer Navigationsoperator - was ist eigentlich los?

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.

17
recursive

Gehen wir das logisch durch.

var f = ???;
var i = f?.Measure;
var t = i.HasValue;

Wir wissen nicht, ob f null ist oder nicht. 

  1. Wenn fist null, dann ist das Ergebnis (i) null 
  2. Wenn fist 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;
  1. Wenn fis null ist, ist das Ergebnis (i) null 
  2. Wenn fist 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.

19
Rob

Nullable<T> ist eigentlich eine Struktur und kann daher nicht null sein, nur seine Value kann, also HasValue immer erreichbar sein.

0
Spencer Hakim
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.

0
user69234