C # 9 Probleme mit nullbaren Typen
Betrachten Sie den folgenden Code (VS 16.8.0 Preview 2.1 C # 9.0 Preview):
#nullable enable
using System.Collections.Generic;
class Archive<T> where T : notnull
{
readonly Dictionary<string, T> Dict = new();
public T? GetAt(string key)
{
return Dict.TryGetValue(key, out var value) ? value : default;
}
}
class Manager
{
public int Age { get; set; }
}
class Main34
{
long F3()
{
Archive<long> a = new();
var johnAge = a.GetAt("john");
if (johnAge is null) return -1; // Error CS0037 Cannot convert null to 'long' because it is a non - nullable value type
return johnAge;
}
long F4()
{
Archive<Manager> a = new();
var johnAge = a.GetAt("john");
//if (johnAge is null) return -1;
return johnAge.Age; // Correct ! warning "Derefrencing of a possibly null reference" will be removed if line above unremarked
}
}
Es fällt mir schwer, die Fehler in F3 zu verstehen / zu beheben. Der Compiler scheint zu glauben, dass es johnAge trotz der Rückkehr des Seins longnicht gibt long?(wie ich durch Bewegen des Mauszeigers in VS bestätigt habe)Archive<T>.GetAtT?
Gibt es eine Möglichkeit, ein generisches Archiv zu haben, das das tut, was ich will (eine GetAt-Methode, die Nullable zurückgibt, selbst wenn T ein nicht nullbarer Basistyp ist, dh lang)?
Antworten
Grundsätzlich kommt es darauf an, dass nullbare Werttypen und nullbare Referenztypen sehr, sehr unterschiedlich sind. Der CLR sind nullbare Werttypen bekannt, aber für die CLR sind nullbare Referenztypen nur "der normale Referenztyp, wobei ein Attribut dem Compiler mitteilt, ob er als nullwert angesehen werden soll oder nicht".
Wenn Tdie notnullEinschränkung vorliegt, wird der Typ T?nur Tin der IL kompiliert . Es muss - es kann nicht kompiliert werden Nullable<T>, da Nullable<T>Einschränkungen Tein Werttyp sein müssen.
Für a Archive<long>gibt die GetAtMethode also 0L zurück, wenn der Schlüssel nicht im Wörterbuch gefunden wird - sie gibt (und kann) nicht den Nullwert von a zurück Nullable<long>, was Ihr Code F3tatsächlich erwartet.
Die gesamte Funktion "nullfähige Referenztypen" leidet unter dem Versuch, ein "Furnier" mit nullfähigem Bewusstsein über ein Typsystem hinzuzufügen, das es grundsätzlich nicht hat. Ich bin sicher, wenn eine neue Laufzeit und Sprache jetzt von Grund auf neu zusammen entworfen würden, würde dies versuchen, dies enger zu vereinheitlichen. So wie es ist, glaube ich, dass das Feature immer noch viel Wert hat - aber es macht die Dinge definitiv wirklich schwierig, wenn es um Generika geht.