Warum wird NullableT als Struktur und nicht als Klasse betrachtet?

8

Ich versuche, eine generische Klasse zu definieren, die einen beliebigen Typ verwendet, der auf null gesetzt werden kann:

%Vor%

Das funktioniert gut. Ich möchte auch eine abgeleitete Klasse erstellen, die jeden primitiven Typ (int, double, usw.) annehmen kann, und einfach das Gleiche wie die obige Klasse auflösen kann, aber wo das Primitive in ein Nullable eingeschlossen ist

%Vor%

Aber aus irgendeinem Grund funktioniert das nicht. Ich erhalte den Fehler: The type 'T?' must be a reference type in order to use it as parameter 'T' in the generic type or method 'BundledValue_Classes<T>'

Ist es klar, was ich hier versuche? Ich möchte nicht den Inhalt der gesamten BundledValue_Classes<T> -Klasse kopieren müssen, nur um den Fall eines Grundelements zu behandeln, das in einem Nullable<T> eingepackt ist.

Vielleicht gibt es eine Möglichkeit, die Typeinschränkung für BundledValue_Classes<T> so festzulegen, dass nicht nur Klassen akzeptiert werden, sondern jeder Typ, dem ein Nullwert zugewiesen werden kann (einschließlich Nullable<T> types), die die einzige Ausnahme darstellen die Regel.)

    
Alain 14.12.2013, 21:57
quelle

2 Antworten

13

Nullable<T> ist eine Struktur, gemäß der Dokumentation . Es ist einfach keine Klasse. Es ist ein Werttyp, der in Bezug auf Felder ein wenig wie folgt aussieht:

%Vor%

Der Wert null für einen Nullable<T> -Typ ist keine Nullreferenz, sondern nur ein Wert, bei dem das Feld hasValue falsch ist.

Beachten Sie, dass Nullable<T> eine Bedingung für eine Einschränkung von where TFoo : struct jedoch nicht erfüllt, da es sich um eine Wertbeschränkung vom Typ nicht nullable handelt. Grundsätzlich erfüllt Nullable<T> weder die Bedingung class noch die struct . Es gibt keine Einschränkung, die nur zulässige Typen zulässt (reference oder Nullable<T> ).

    
Jon Skeet 14.12.2013, 21:58
quelle
0

Wie bereits erwähnt, ist der Typ Nullable<T> eine Struktur, die ein T einkapselt, und ein Flag, das angibt, ob es gültig ist. Da die Implementierer von .NET keinen Nutzen darin sahen, einen Typ zu haben, der eine Sache kapseln konnte und angeben konnte, ob sie gültig war, entschieden sie, dass sie Nullable<Nullable<T>> nicht zulassen wollten Ich mag übrigens nicht], und anstatt eine spezielle Einschränkung nur für den generischen Parameter in Nullable<T> zu entwickeln, haben sie entschieden, dass, obwohl Nullable<T> eine Struktur ist, sie einer struct Typabhängigkeit nicht genügen sollte .

Persönlich hätte ich lieber Nullable<T> gesehen, sei einfach eine "gewöhnliche" Struktur mit exponierten Feldern vom Typ bool und unbeschränkter T , die z. Dictionary.TryGetValue , um einen Wert zurückzugeben und anzugeben, ob es gültig war (unabhängig davon, ob TValue eine Klasse, eine nicht nullbare Struktur oder eine Nullable<T> war) oder eine Klasse mit T . Der Wert, someNullable != null als Abkürzung zu sagen, ist im Vergleich zu der Verwirrung und den damit verbundenen Komplikationen im Vergleich zu someNullable.HasValue winzig. Trotzdem, .NET ist was es ist. Persönlich würde ich vorschlagen, Nullwert-Typen generell zu vermeiden, da man mit einem NULL-fähigen Typ vieles nicht machen kann, ohne zuerst den Wert zu kopieren. Solche Typen haben auch einige merkwürdige Macken in Bezug auf Thread-Sicherheit (zB Code, der Nullable<T> erhält und beobachtet, dass HasValue nicht sicher annehmen kann, dass GetValueOrDefault Default(T) zurückgibt, auch wenn nichts die% co_de geändert haben kann % seit dem Empfang).

    
supercat 16.12.2013 04:32
quelle