2010-01-08 18 views
13

Haben Sie schon einmal versucht, die Convert.ChangeType() Methode zu verwenden, um einen Wert in einen Nullable<T> Typ zu konvertieren? Unbeholfen wirft es einen InvalidCastException Sprichwort "Null-Objekt kann nicht in einen Werttyp konvertiert werden".Warum wird Nullable <T> als Werttyp betrachtet?

Versuchen Sie, diese auf Ihrem sofortigen Fenster: ?System.Convert.ChangeType(null, typeof(int?))

aus unerfindlichen Gründen, nullables sind Typen betrachtet Wert. Zum Beispiel gibt typeof(int?).IsValueTypetrue zurück.

Für mich, seit Nullable<T> akzeptieren null, es ist ein Klassentyp, kein Werttyp. Weiß jemand, warum es anders umgesetzt würde?

Antwort

27

System.Nullable<T> ist technisch eine Struktur, so dass es ein Werttyp (der null Wert für ein Nullable<T> nicht genau dasselbe ist wie eine Null-Referenz. Es ist ein boolesches Flag, das das Fehlen eines Wertes bezeichnet.) Allerdings ist es behandelt speziell von der Laufzeit und das macht es zu einem unangenehmen Werttyp. Erstens erfüllt es nicht where T : struct Typ Einschränkung (es entspricht nicht where T : class entweder, was es wert ist). Zweitens zeigt es ein interessantes Boxverhalten. ein Nullable<T> Boxen wird in Folge:

  • A null Referenz, wenn der Wert null ist.
  • Ein Boxed-Wert des zugrunde liegenden Typs, wenn es tatsächlich einen Wert enthält. Das heißt, in den Aussagen:

    int? x = 2; 
    object y = x; 
    

    y ist kein boxed Nullable<int>. Es ist einfach eine Box int. Sie können jeden Boxed-Wert vom Typ T bis Nullable<T> (und natürlich T) auspacken. Wird ein null Verweis auf Nullable<T> geworfen, ergibt sich ein null Wert (wie Sie vielleicht erwarten).

Diese spezielle Behandlung durch die Laufzeit macht Nullable Types auf den Weg null Arbeiten in Referenztypen ähnlichen arbeiten.

+3

Das seltsame Boxverhalten dauert eine Weile, aber ich bin froh, dass es so ist; andernfalls würde viel von dem Wert von Nullable (der von Wert kommt, der Transparenz überschreitet) verloren gehen. – LBushkin

+1

Eigentlich war das Boxverhalten eine Änderung, die spät im Entwicklungszyklus von .NET 2.0 geschah. In frühen Betas war 'Nullable ' eine einfache Struktur. In der Praxis, wenn Sie tatsächlich Nullable-Typen verwenden, um nicht vorhandene Werte zu speichern, empfinde ich dieses Verhalten auch als natürlicher. –

+0

Tolle zusätzliche Informationen übrigens – Nick

11

Nullable<T> ein Werttyp (es ist ein struct findet in den MSDN documentation), aber es gibt eine implizite Konvertierung von null zu einem Nullable<T> ohne Wert (x.HasValue == false). Es gibt auch eine implizite Konvertierung von Werten vom Typ T in Werte vom Typ Nullable<T>.

Zusätzlich werden alle Operatoren aus den regulären Typen entfernt, um direkt mit Nullable-Typen zu arbeiten.

+0

Warum der Downvote? Ich habe mich geirrt? Wenn ja, bitte erleuchte mich. –

+0

Ich habe Upvoted, um Downvote abzubrechen. :) –

2

Nullable<T> ist als eine Struktur implementiert und Strukturen sind Werttypen.

+1

Aber keine Struktur kann einen 'Null'-Wert erhalten. Ich glaube, dass Nullables verschieden genug von Strukturen sind, um nicht als Strukturen betrachtet zu werden. – jpbochi

+2

'Nullable ' kann auch keinen 'null'-Wert erhalten, es hat nur eine implizite Umwandlung in und von 'null'. Sie können dies auf jeder benutzerdefinierten Struktur implementieren, wenn Sie dies wünschen. – Aaronaught

+4

@Aaronaught: Sie können etwas * ähnliches * mit einer benutzerdefinierten Struktur tun, aber eine Menge des Verhaltens der Nullable-Typen kann nicht durch Code nachgeahmt werden. Nullable-Werte sind nicht nur eine Bibliothekslösung. Sie bekommen spezielle Unterstützung vom Compiler (und auch von der CLR, denke ich). –

1

Ich habe gerade diese Frage in der Liste "Verwandte Fragen" unter Why Nullable<T> is a struct? gesehen und ich denke meine Antwort dort gilt auch hier. Der ganze Sinn von Nullable<T> ist, in jeder Hinsicht wie ein Werttyp zu handeln, außer der Fähigkeit, einen Nullwert zu nehmen.

Der Nullwert einer Nullreferenz kann auf zwei Arten betrachtet werden.Einer ist, dass er nichts referenziert, ein anderer ist, dass er keinen bedeutungsvollen Wert hat. Diese Dinge sind zwei verschiedene Arten, dasselbe zu sagen, aber sie haben unterschiedliche Anwendungen.

Nullable<T> gibt uns die Möglichkeit zu sagen, "das hat keinen sinnvollen Wert" und in diesem Ausmaß kann es die gleiche Semantik wie eine Nullreferenz haben, aber es ist nicht wie eine Referenz in anderer Weise. Wenn null ist es Nichtigkeit ist rein, dass "kein sinnvoller Wert" null - nicht "bezieht sich auf nichts" und wenn nicht null es hält einen Wert, nicht darauf Bezug nehmend. 0 Aaronaught argumentiert, dass dies bedeutet, eine Nullable kann nicht wirklich Null enthalten, während ich nicht zustimmen, weil auf der Ebene, auf der es verwendet wird, eine semantische Null haben kann, ist sein Punkt in Betracht zu ziehen, selbst wenn "Null" a Nullable ist anders als eine Referenz - in Wirklichkeit ist unsere Meinungsverschiedenheit eine Frage, auf welcher Ebene der Abstraktion wir uns entscheiden.

Verwandte Themen