10 Stimmen

Nullable<T> Verwirrung

Warum ist das Folgende verboten?

Nullable<Nullable<int>>

während

struct MyNullable <T>
{

}

MyNullable<Nullable<int>> 

ist NICHT

19voto

ShuggyCoUk Punkte 35230

Das liegt daran, dass die struct-Beschränkung eigentlich bedeutet nicht löschbar'. da Nullable, obwohl es eine Struktur ist, nullable ist (den Wert null annehmen kann), ist die Nullable<int> kein gültiger Typparameter für das äußere Nullable ist.

Dies wird deutlich in die Dokumentation der Zwänge

wobei T: Struktur
Das Argument type muss ein Wertetyp sein. Jeder Werttyp außer Nullable kann angegeben werden.
Weitere Informationen finden Sie unter Verwenden von nullbaren Typen (C# Programmierhandbuch).

Wenn Sie die Gründe dafür wissen wollen, brauchen Sie die Kommentare des Sprachentwicklers dazu, die ich nicht finden kann. Ich würde das jedoch unterstellen:

  1. die Compiler- und Plattform-Änderungen, die erforderlich sind, um Nullable in seiner jetzigen Form zu erreichen, sind ziemlich umfangreich (und wurden in relativ letzter Minute zur Version 2.0 hinzugefügt).
  2. Sie haben mehrere potenziell verwirrende Sonderfälle.

Das Zulassen des Äquivalents von int?? würde nur Verwirrung stiften, da die Sprache keine Möglichkeit zur Unterscheidung von Nullable <Nullable<null>> und Nullable <null> noch eine offensichtliche Lösung für die folgenden Fragen.

Nullable<Nullable<int>> x = null;
Nullable<int> y = null;
Console.WriteLine(x == null); // true
Console.WriteLine(y == null); // true
Console.WriteLine(x == y); // false or a compile time error!

Die Rückgabe von true würde bedeuten sehr komplexer und erheblicher Overhead bei vielen Operationen mit dem Typ Nullable.

Einige Typen in der CLR sind "besonders", z. B. Strings und Primitive, da der Compiler und die Laufzeitumgebung viel über die jeweils andere Implementierung wissen. Nullable ist in dieser Hinsicht auch etwas Besonderes. Da es bereits in anderen Bereichen special cased ist, ist das where T : struct Aspekt ist keine so große Sache. Der Vorteil liegt im Umgang mit Structs in generischen Klassen, da keine von ihnen, abgesehen von Nullable, mit Null verglichen werden kann. Das bedeutet, dass das Jit sicher betrachten kann t == null immer falsch zu sein.

Wenn Sprachen so konzipiert sind, dass zwei sehr unterschiedliche Konzepte interagieren können, kommt es häufig zu seltsamen, verwirrenden oder sogar gefährlichen Randfällen. Betrachten wir als Beispiel Nullable und die Gleichheitsoperatoren

int? x = null;
int? y = null;
Console.WriteLine(x == y); // true
Console.WriteLine(x >= y); // false!     

Durch die Vermeidung von Nullables bei der Verwendung von struct generic constraint können viele unangenehme (und unklare) Randfälle vermieden werden.

Was den genauen Teil der Spezifikation betrifft, der dies vorschreibt aus Abschnitt 25.7 (Hervorhebung von mir):

Die Werttyp-Beschränkung legt fest, dass ein Typ-Argument ein Werttyp sein muss (§25.7.1). Jede nicht-nullbare Parameter, der die Werttyp-Beschränkung hat, erfüllt diese Beschränkung. Ein Typ-Parameter der die Werttyp-Beschränkung hat, darf nicht auch die Konstruktor-Beschränkung haben. Der System.Nullable-Typ spezifiziert die nicht-nullbare Werttyp-Beschränkung So können rekursiv konstruierte Typen der Formen T?? und Nullable < Nullbar < T >> sind verboten.

14voto

recursive Punkte 80517

Ich glaube, Sie können nur nicht-nullbare Werttypen in Nullable s. Da Nullable selbst löschbar ist, ist eine Verschachtelung auf diese Weise verboten.

De http://msdn.microsoft.com/en-us/library/kwxxazwb.aspx

public Nullable(
    T value
)

Art: T Ein Werttyp.

3voto

Curt Hagenlocher Punkte 20150

Nullable ist besonders, weil es explizite Unterstützung für Boxing und Unboxing von Nullable-Typen in die CLR eingebaut ist:

Wenn Sie die MSIL box Anweisung gegen eine Nullable<T> erhalten Sie tatsächlich eine null als das Ergebnis. Es gibt keinen anderen Wertetyp, der beim Einrahmen eine Null ergibt.

Es gibt eine ähnliche und symmetrische Unterstützung für das Unboxing.

2voto

Noldorin Punkte 138548

Der generische Typ-Parameter für Nullable muss selbst ein nicht-nullbarer Typ sein (d.h. ein Werttyp). Dies ist die C#-Compiler-Warnung, die ich erhalte, und es scheint Sinn zu machen. Sagen Sie mir, warum würden Sie so etwas überhaupt tun wollen? Ich persönlich sehe keinen Nutzen und auch wenig Sinn in einer solchen Deklaration.

0voto

tvanfosson Punkte 506878

Nullable ermöglicht es, einen Werttyp wie einen Referenztyp zu behandeln, in dem Sinne, dass der Wert entweder existiert oder nicht (null ist). Da ein Referenztyp bereits nullable ist, ist dies nicht zulässig.

Zitiert von MSDN :

Die Struktur Nullable(T) unterstützt nur die Verwendung eines Werttyps als nullable Typ, weil Referenztypen vom Design her nullbar sind.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X