Problèmes de types Nullable C # 9
Considérez le code suivant (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
}
}
J'ai du mal à comprendre / résoudre les erreurs de F3, on dirait que le compilateur pense que johnAge n'existe longpas long?(comme je l'ai vérifié en le survolant dans VS) malgré le retour de l' Archive<T>.GetAtêtreT?
Existe-t-il un moyen d'avoir une archive générique qui fera ce que je veux (une méthode GetAt qui retourne Nullable même lorsque T est un type de base non nullable, c'est-à-dire long)?
Réponses
Fondamentalement, cela se résume à des types de valeur Nullable et des types de référence Nullable étant très, très différents. Le CLR est conscient des types de valeur Nullable, mais en ce qui concerne le CLR, les types de référence Nullable sont simplement "le type de référence normal, avec un attribut indiquant au compilateur s'il doit ou non être considéré comme Nullable".
Quand Ta la notnullcontrainte, le type T?se compile simplement Tdans l'IL. Il doit - il ne peut pas être compilé Nullable<T>, car les Nullable<T>contraintes Tdoivent être un type valeur.
Donc, pour an Archive<long>, la GetAtméthode retournera 0L si la clé n'est pas trouvée dans le dictionnaire - elle ne retournera pas (et ne peut pas) retourner la valeur nulle de a Nullable<long>, ce que votre code F3attend effectivement.
L'ensemble de la fonctionnalité "types de référence nullable" souffre d'être une tentative d'ajouter un "placage" de reconnaissance nullable sur un système de types qui, fondamentalement, ne l'a pas. Je suis sûr que si un nouveau runtime et un nouveau langage étaient conçus ensemble à partir de zéro maintenant, il essaierait de l'unifier plus étroitement. Dans l'état actuel des choses, je pense que la fonctionnalité a encore beaucoup de valeur - mais cela rend vraiment les choses vraiment délicates en ce qui concerne les génériques.