Essayer de rendre Feature
générique puis soudain le compilateur dit
Opérateur ‘?’ ne peut pas être appliqué à l’opérande de type ‘T’
Voici le code
public abstract class Feature { public T Value { get { return GetValue?.Invoke(); } // here is error set { SetValue?.Invoke(value); } } public Func GetValue { get; set; } public Action SetValue { get; set; } }
Il est possible d’utiliser ce code à la place
get { if (GetValue != null) return GetValue(); return default(T); }
Mais je me demande comment réparer ce joli one-line C # 6.0.
Puisque tout ne peut pas être null
, vous devez restreindre T
pour que quelque chose soit null
(un object
). Les structures ne peuvent pas être nulles, et les enums non plus.
L’ajout d’une class
Where à résoudre le problème:
public abstract class Feature where T : class
Alors, pourquoi ça ne marche pas?
Invoke()
donne T
Si GetValue
est null
, le ?
L’opérateur définit la valeur de retour du type T
sur null
, ce qu’il ne peut pas. Si T
est int
par exemple, il ne peut pas la rendre nulle ( int?
) Car le type requirejs ( T
= int
) ne l’est pas.
Si vous changez T
pour être int
dans votre code, vous verrez le problème très clairement. Le résultat final de ce que vous demandez est ceci:
get { int? x = GetValue?.Invoke(); return x.GetValueOrDefault(0); }
Ce n’est pas quelque chose que l’opérateur de propagation nulle fera pour vous. Si vous revenez à l’utilisation de default(T)
il sait exactement quoi faire et vous évitez la propagation de “problèmes” de null.
T
doit être un type de référence ou un type nullable
public abstract class Feature where T : class { // ... }
Pour autant que je sache le ?.
L’opérateur est codé en dur pour fonctionner avec null
, c’est-à-dire qu’il fonctionne pour les types de référence ou les types de valeur nullable, mais pas les types de valeur normaux . Le problème est probablement que l’opérateur retourne la valeur null
si l’expression était null
au lieu de la default(T)
.
Vous pourrez peut-être résoudre ce problème en limitant T
à la class
ici.