Frage

Warum ist das folgende verboten?

Nullable<Nullable<int>>

wohingegen

struct MyNullable <T>
{


}

MyNullable<Nullable<int>> 

ist nicht

War es hilfreich?

Lösung

Dies liegt daran, dass die Strukturbeschränkung tatsächlich bedeutet "Nicht nullbar" Da nullbar ist, trotz der Struktur, kann er nicht nullbar sind (kann den Wert null akzeptieren) die Nullable<int> ist kein gültiger Typparameter für das äußere Nullable.

Dies ist explizit in Die Dokumentation der Einschränkungen

Wo T: Struktur
Das Typ -Argument muss ein Werttyp sein. Jeder Werttyp, der nicht nullbar ist, kann angegeben werden.
Weitere Informationen finden Sie unter Verwendung von Nullable -Typen (C# -Programmierhandbuch).

Wenn Sie die Begründung dafür möchten, benötigen Sie die Kommentare des tatsächlichen Sprachdesigners dazu, die ich nicht finden kann. Ich würde das jedoch postulieren:

  1. Der Compiler und die Plattformänderungen, die erforderlich sind, um in seiner aktuellen Form Nullierbar zu erreichen, sind ziemlich umfangreich (und waren eine relativ letzte Minute zu der 2.0 -Version).
  2. Sie haben mehrere potenziell verwirrende Randfälle.

Das Äquivalent von int ?? würde dies nur verwirren, da die Sprache keine Möglichkeit bietet, nullbar zu unterscheiden<Nullable<null>> und nullbar<null> noch eine offensichtliche Lösung für Folgendes.

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!

Diese Rückkehr wahr zu machen, wäre sehr Komplexer und signifikanter Aufwand bei vielen Operationen, an denen der typische Typ beteiligt ist.

Einige Typen in der CLR sind "speziell". Beispiele sind Saiten und Grundelemente, da der Compiler und die Laufzeit viel über die voneinander verwendete Implementierung wissen. Nullierbar ist auch auf diese Weise besonders. Da ist es bereits in anderen Bereichen Spezialgehäuse Spezialgehäuse where T : struct Aspekt ist keine so große Sache. Der Vorteil davon ist der Umgang mit Strukturen in generischen Klassen, da keiner von ihnen, abgesehen von Nullable, mit Null verglichen werden kann. Dies bedeutet, dass die JIT sicher berücksichtigen kann t == null immer falsch sein.

Wenn Sprachen so konzipiert sind, dass zwei sehr unterschiedliche Konzepte interagieren, werden Sie tendenziell seltsame, verwirrende oder rechte gefährliche Randfälle. Als Beispiel als nullierbar und die Gleichstellungsoperatoren betrachten

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

Durch Verhinderung von Nullables bei Verwendung von strukturgen Generika können viele böse (und unklare) Kantenfälle vermieden werden.

In Bezug auf den genauen Teil der Spezifikation, die dies vorschreibt Aus Abschnitt 25.7 (Hervorhebung meiner):

Die Einschränkung des Werttyps gibt an, dass ein für den Typ Parameter verwendetes Typ Argument ein Werttyp sein muss (§25.7.1). Jeder Parameter mit nicht nullbarer Strukturart, Enum oder Typ mit der Einschränkung des Werttyps erfüllt diese Einschränkung. Ein Typ-Parameter mit der Einschränkung des Werttyps darf nicht auch die Konstruktor-Einstörungen aufweisen. Das System. So rekursiv konstruierte Typen der Formen t ?? und nullbar<Nullbar<T>> sind verboten.

Andere Tipps

Ich glaube, Sie können nur nicht nullbare Werttypen verwenden Nullables. Seit Nullable selbst ist nullbar, es ist verboten, diese Weise zu nisten.

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

public Nullable(
    T value
)

Typ: TA -Werttyp.

Nullierbar ist etwas Besonderes, da es explizite Unterstützung für das Boxen und das Unboxing von in das CLR eingebauten Typen gibt:

Wenn Sie den MSIL verwenden box Anweisung gegen a Nullable<T>, Sie werden tatsächlich eine bekommen null als Ergebnis. Es gibt keinen anderen Werttyp, der beim Boxen einen Null erzeugt.

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

Der generische Typparameter für Nullierbar muss selbst ein nicht nullbarer Typ sein (dh Werttyp). Dies ist die C# Compiler -Warnung, die ich bekomme, und es scheint Sinn zu machen. Sag mir, warum willst du so etwas überhaupt tun? Ich persönlich kann für eine solche Erklärung keine Verwendung und wenig Sinn sehen.

Nullierbar ermöglicht es Ihnen, einen Werttyp zu nehmen und ihn wie einen Referenztyp zu machen, in dem Sinne, dass der Wert entweder existiert oder nicht (ist null). Da ein Referenztyp bereits nullbar ist, ist er nicht zulässig.

Zitiert aus Msdn:

Die Nullable (T) -Struktur unterstützt nur einen Werttyp als nullierbares Typ, da Referenztypen für das Design nullbar sind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top