Warum kann ein int? auf null gesetzt haben instance properties?

7

Ich bin neugierig, warum der folgende Code funktioniert (unter dem VS-Debugger ausgeführt):

%Vor%

Wenn x tatsächlich null ist, auf welche Instanz bezieht sich HasValue ? Ist HasValue als eine Erweiterungsmethode implementiert, oder macht der Compiler Sonderfall, um es magisch arbeiten zu lassen?

    
Mike Christensen 20.12.2011, 20:20
quelle

9 Antworten

9

Weil x kein Referenztyp ist. Das ? ist nur syntaktischer Zucker für Nullable<T> , was ein struct ( Werttyp).

    
Cameron 20.12.2011, 20:22
quelle
5

int? ist eigentlich eine Struktur Nullable<int> . Daher kann Ihr x nicht null sein, weil es immer eine Instanz einer Struktur ist.

    
Sergei B. 20.12.2011 20:22
quelle
4

Hand-waving-Antwort: Nullable Strukturen sind magisch.

Längere Antwort: Null ist eigentlich nicht das, was durch den Wert repräsentiert wird. Wenn Sie einer Nullable-Struktur null zuweisen, ist das, was Sie hinter den Kulissen sehen, anders.

%Vor%

In diesem Fall wird eine Instanz der Struktur erstellt, für die T Value auf einen Standardwert und die bool HasValue -Eigenschaft auf false festgelegt ist.

Das einzige Mal, dass Sie eine Null -Referenz von Nullable<T> erhalten, ist die Box, wenn Nullable<T> direkt an T oder null hängt, je nachdem, ob der Wert ist eingestellt.

    
Anthony Pegram 20.12.2011 20:24
quelle
2

Es gibt mehrere Bedeutungen für null .

Einer in Programmiersprachen, die Variablen und Speicher zeigerbasiert darstellen (was die Referenzen von C # einschließt, obwohl einige der Details ausgeblendet sind) ist "das zeigt nichts".

Ein anderer ist "das hat keinen bedeutungsvollen Wert".

Bei Referenztypen verwenden wir häufig die erstere, um letztere darzustellen. Wir könnten string label = null verwenden, um "keine aussagekräftige Bezeichnung zu bedeuten. Es bleibt jedoch, dass es immer noch auch eine Frage dessen ist, was im Speicher vor sich geht und was darauf hinweist. Trotzdem ist es hübsch Was für eine Schande, dass wir das nicht mit int und DateTime in C # 1.1 machen konnten

Das ist Nullable<T> , ein Mittel, um "keinen sinnvollen Wert" zu sagen, aber auf der darunter liegenden Ebene ist es nicht null in der gleichen Weise wie eine null Zeichenkette (außer in der Box). Es wurde null zugewiesen und ist gleich null, daher ist es logisch null und null entsprechend einigen anderen Semantiken, aber es ist nicht Null in der Implementierungsdifferenz zwischen Referenz- und Werttypen "zeigt nicht auf irgendetwas".

Es ist nur der "auf nichts zeigen" -Aspekt des Nullen vom Referenztyp, der Sie daran hindert, Instanzmethoden darauf aufzurufen.

Und tatsächlich, selbst das ist nicht ganz richtig. Mit IL können Sie Instanzmethoden für eine Nullreferenz aufrufen, und solange sie nicht mit Feldern interagiert, funktioniert sie. Es kann nicht funktionieren, wenn es (direkt oder indirekt) diese Felder benötigt, da sie nicht in einer Nullreferenz existieren, aber es könnte null.FineWithNull() aufrufen, wenn diese Methode wie folgt definiert wurde:

%Vor%

Mit C # wurde beschlossen, dies zu verbieten, aber es ist keine Regel für alle .NET (ich denke F # erlaubt es, aber ich bin mir nicht sicher, ich weiß, dass nicht verwaltetes C ++ es erlaubt und es in einigen sehr seltenen Fällen nützlich war ).

    
Jon Hanna 20.12.2011 23:57
quelle
1

Wenn Sie int? x = null verwenden, wird x eine neue Instanz von Nullable<int> zugewiesen und ihr Wert wird auf null gesetzt.

Ich kenne die Interna nicht genau, aber ich würde annehmen, dass der Zuweisungsoperator selbst etwas überladen ist.

    
Dennis Traub 20.12.2011 20:22
quelle
1

Ein Nullable-Typ ist nicht wirklich null , da es immer noch nicht umgeht, dass Werttypen nicht null sein können. Es ist stattdessen eine Referenz auf die Nullable<> struct (die auch ein Werttyp ist und nicht null sein kann).

Weitere Informationen hier .

Grundsätzlich beziehen Sie sich immer auf eine Instanz von etwas, wenn Sie einen nullfähigen Typ verwenden. Die Standardinformationen, die von dieser Referenz zurückgegeben werden, sind der gespeicherte Wert (oder null , wenn kein Wert gespeichert ist).

    
David 20.12.2011 20:23
quelle
1

Nullable ist nicht wirklich ein Referenztyp und seine Instanzmethoden sind einer der Orte, an denen dies angezeigt wird. Grundsätzlich handelt es sich um einen Strukturtyp, der ein boolesches Flag und einen Wert des Typs enthält, für den ein Nullwert zulässig ist. Die Sprachen Spezialfall verschiedene Operatoren [zu heben, oder zu betrachten (bool?) Null in einigen Fällen falsch] und das Null-Literal, und die Laufzeit Spezialfälle Boxen, aber abgesehen davon ist es nur eine Struktur.

>     
Random832 20.12.2011 20:23
quelle
1

Es ist ein völlig neuer Typ. Nullable ist nicht T.

Was Sie haben, ist eine generische Klasse, etwa so:

%Vor%

Ich bin mir sicher, dass da mehr dahinter steckt (besonders im Getter und Setter, aber das ist es in aller Kürze.

    
Mike Hofer 20.12.2011 20:24
quelle
0

Der Nullable-Typ (in diesem Fall: nullable int) hat eine Eigenschaft von HasValue, die boolesch ist. Wenn HasValue True ist, hat die Value-Eigenschaft (vom Typ T, in diesem Fall ein int) einen gültigen Wert.

    
AllenG 20.12.2011 20:22
quelle

Tags und Links