Donc j'ai cette classe:
public class Foo<T> where T : ???
{
private T item;
public bool IsNull()
{
return item == null;
}
}
Maintenant, je recherche une contrainte de type qui me permet d'utiliser tout comme paramètre de type qui peut l'être null
. Cela signifie tous les types de référence, ainsi que tous les types Nullable
( T?
):
Foo<String> ... = ...
Foo<int?> ... = ...
devrait être possible.
Utiliser class
comme contrainte de type me permet uniquement d'utiliser les types de référence.
Informations supplémentaires:
J'écris une application de tuyaux et de filtres et je souhaite utiliser une null
référence comme dernier élément qui passe dans le pipeline, afin que chaque filtre puisse s'arrêter correctement, faire un nettoyage, etc.
IFoo<T>
comme type de travail et créer des instances via une méthode d'usine? Cela pourrait fonctionner.Réponses:
Si vous êtes prêt à effectuer une vérification à l'exécution dans le constructeur de Foo plutôt que d'avoir une vérification à la compilation, vous pouvez vérifier si le type n'est pas un type référence ou Nullable, et lever une exception si c'est le cas.
Je me rends compte que seule une vérification à l'exécution peut être inacceptable, mais juste au cas où:
Ensuite, le code suivant se compile, mais le dernier (
foo3
) lève une exception dans le constructeur:la source
static bool isValidType
champ que vous avez défini dans le constructeur statique, puis vérifiez simplement cet indicateur dans le constructeur d'instance et lancez s'il s'agit d'un type non valide afin que vous ne fassiez pas tout le travail de vérification à chaque fois que vous construisez une instance. J'utilise souvent ce modèle.Je ne sais pas comment implémenter l'équivalent de OR en génériques. Cependant je peux proposer d'utiliser le mot clé par défaut afin de créer null pour les types Nullable et 0 valeur pour les structures:
Vous pouvez également implémenter votre version de Nullable:
Exemple:
la source
Je suis tombé sur ce problème pour un cas plus simple de vouloir une méthode statique générique qui pourrait prendre n'importe quoi "nullable" (soit des types de référence ou Nullables), ce qui m'a amené à cette question sans solution satisfaisante. J'ai donc proposé ma propre solution qui était relativement plus facile à résoudre que la question posée par l'OP en ayant simplement deux méthodes surchargées, une qui prend a
T
et a la contraintewhere T : class
et une autre qui prend aT?
et awhere T : struct
.J'ai alors réalisé que cette solution pouvait également être appliquée à ce problème pour créer une solution vérifiable au moment de la compilation en rendant le constructeur privé (ou protégé) et en utilisant une méthode de fabrique statique:
Maintenant, nous pouvons l'utiliser comme ceci:
Si vous voulez un constructeur sans paramètre, vous n'obtiendrez pas la subtilité de la surcharge, mais vous pouvez toujours faire quelque chose comme ceci:
Et utilisez-le comme ceci:
Il y a peu d'inconvénients à cette solution, l'un est que vous préférerez peut-être utiliser «nouveau» pour construire des objets. Une autre est que vous ne serez pas en mesure d'utiliser
Foo<T>
comme argument de type générique pour une contrainte de type de quelque chose comme:where TFoo: new()
. Enfin, il y a le peu de code supplémentaire dont vous avez besoin ici, ce qui augmenterait surtout si vous avez besoin de plusieurs constructeurs surchargés.la source
Comme mentionné, vous ne pouvez pas effectuer de vérification à la compilation. Les contraintes génériques dans .NET font cruellement défaut et ne prennent pas en charge la plupart des scénarios.
Cependant, je considère que c'est une meilleure solution pour la vérification au moment de l'exécution. Il peut être optimisé au moment de la compilation JIT, car ce sont tous les deux des constantes.
la source
Une telle contrainte de type n'est pas possible. Selon la documentation des contraintes de type, il n'y a pas de contrainte qui capture à la fois les types Nullable et Reference. Puisque les contraintes ne peuvent être combinées que dans une conjonction, il n'y a aucun moyen de créer une telle contrainte par combinaison.
Vous pouvez, cependant, pour vos besoins, revenir à un paramètre de type non contraint, car vous pouvez toujours vérifier == null. Si le type est un type valeur, la vérification sera toujours évaluée à false. Ensuite, vous obtiendrez peut-être l'avertissement R # "Comparaison possible du type valeur avec null", ce qui n'est pas critique, tant que la sémantique vous convient.
Une alternative pourrait être d'utiliser
au lieu du contrôle nul, depuis la valeur par défaut (T) où T: class est toujours nul. Cependant, cela signifie que vous ne pouvez pas distinguer le temps qu'une valeur non nullable n'a jamais été définie explicitement ou a simplement été définie sur sa valeur par défaut.
la source
j'utilise
la source
la source