Partager via


Résoudre les erreurs et les avertissements liés aux paramètres de type générique et aux arguments de type générique

Cet article traite des erreurs suivantes du compilateur :

  • CS0080 : Les contraintes ne sont pas autorisées sur les déclarations non génériques.
  • CS0081 : La déclaration de paramètre de type doit être un identificateur, et non un type.
  • CS0224 : Une méthode avec vararg ne peut pas être générique, être dans un type générique ou avoir un paramètre params.
  • CS0304 : Impossible de créer une instance du type de variable, car elle n’a pas la new() contrainte.
  • CS0305 : L’utilisation du type générique nécessite des arguments de type N.
  • CS0306 : Le type peut ne pas être utilisé comme argument de type.
  • CS0307 : L’identificateur n’est pas une méthode générique. Si vous avez prévu une liste d’expressions, utilisez des parenthèses autour de l’expression.
  • CS0308 : Impossible d’utiliser la méthode ou le type non générique avec des arguments de type.
  • CS0310 : Le type doit être un type non abstrait avec un constructeur sans paramètre public afin de l’utiliser comme paramètre dans le type générique ou la méthode.
  • CS0311 : Le type ne peut pas être utilisé comme paramètre T de type dans le type générique ou la méthode. Il n’existe aucune conversion de référence implicite de type1 en type2.
  • CS0312 : Le type 'type1' ne peut pas être utilisé comme paramètre de type dans le type générique ou la méthode. Le type nullable 'type1' ne répond pas à la contrainte.
  • CS0313 : Le type 'type1' ne peut pas être utilisé comme paramètre de type dans le type générique ou la méthode. Le type nullable 'type1' ne répond pas à la contrainte. Les types nullables ne peuvent pas satisfaire à des contraintes d’interface.
  • CS0314 : Le type ne peut pas être utilisé comme paramètre de type dans le type générique ou la méthode. Il n’existe aucune conversion par boxing ou conversion de type de paramètre.
  • CS0315 : Le type ne peut pas être utilisé comme paramètre T de type dans le type générique ou la méthode. Il n’y a pas de conversion de boxe.
  • CS0401 : La new() contrainte doit être la dernière contrainte spécifiée.
  • CS0403 : Impossible de convertir null en paramètre de type, car il peut s’agir d’un type valeur non nullable. Envisagez plutôt d’utiliser default(T) .
  • CS0405 : Contrainte dupliquée pour le paramètre de type.
  • CS0412: Paramètre : un paramètre, une variable locale ou une fonction locale ne peut pas avoir le même nom qu’un paramètre de type de méthode.
  • CS0413 : Le paramètre de type ne peut pas être utilisé avec l’opérateur as , car il n’a pas de contrainte de type de classe ni de class contrainte.
  • CS0417 : Identificateur : ne peut pas fournir d’arguments lors de la création d’une instance d’un type de variable.
  • CS0449 : Les contraintes class, struct, unmanaged, notnull et default ne peuvent pas être combinées ou dupliquées, et doivent être spécifiées en premier dans la liste des contraintes.
  • CS0450 : Paramètre de type : ne peut pas spécifier à la fois une classe de contrainte et la contrainte class ou struct.
  • CS0451 : La new() contrainte ne peut pas être utilisée avec la struct contrainte.
  • CS0454 : dépendance de contrainte circulaire impliquant le paramètre de type 1 et le paramètre de type 2.
  • CS0455 : Le paramètre de type hérite des contraintes conflictuelles.
  • CS0694 : Le paramètre de type a le même nom que le type ou la méthode conteneur.
  • CS0695 : T impossible d’implémenter les deux interfaces, car elles peuvent unifier pour certaines substitutions de paramètres de type.
  • CS0698 : un type générique ne peut pas dériver du type, car il s’agit d’une classe d’attributs.
  • CS0702 : La contrainte ne peut pas être une classe spéciale.
  • CS0703 : Accessibilité incohérente : le type de contrainte est moins accessible que la déclaration.
  • CS0706 : Type de contrainte non valide. Un type utilisé comme contrainte doit être une interface, une classe non scellée ou un paramètre de type.
  • CS0717 : Classe statique : les classes statiques ne peuvent pas être utilisées comme contraintes.
  • CS1961 : Variance non valide : le paramètre de type doit être validement variant sur le type.
  • CS7002 : Utilisation inattendue d’un nom générique.
  • CS8322 : Impossible de passer un argument avec un type dynamique à une fonction locale générique avec des arguments de type déduits.
  • CS9011 : Le mot clé delegate ne peut pas être utilisé comme contrainte. Tu veux dire System.Delegate?
  • CS9012 : mot clé recordinattendu . Tu veux dire record struct ou record class?
  • CS9338 : Accessibilité incohérente : le type est moins accessible que la classe.

Déclaration de paramètre de type et nommage

Les erreurs suivantes concernent la façon dont vous déclarez et nommez des paramètres de type dans les types et méthodes génériques :

  • CS0080 : Les contraintes ne sont pas autorisées sur les déclarations non génériques.
  • CS0081 : La déclaration de paramètre de type doit être un identificateur, et non un type.
  • CS0412: Paramètre : un paramètre, une variable locale ou une fonction locale ne peut pas avoir le même nom qu’un paramètre de type de méthode.
  • CS0694 : Le paramètre de type a le même nom que le type ou la méthode conteneur.
  • CS9012 : mot clé recordinattendu . Tu veux dire record struct ou record class?

Pour corriger ces erreurs, vérifiez que vous déclarez des paramètres de type avec des identificateurs valides, appliquez des clauses de contrainte uniquement aux déclarations génériques et évitez les conflits de nommage avec d’autres identificateurs dans l’étendue :

  • Supprimez la clause de contrainte des déclarations non génériques (CS0080). La where clause ne peut être utilisée que sur les types génériques et les méthodes qui déclarent des paramètres de type, car les contraintes définissent les exigences que les arguments de type doivent satisfaire. Si vous devez appliquer des contraintes, commencez par ajouter des paramètres de type à votre déclaration de type ou de méthode. Par exemple, remplacez public class MyClass where MyClass : System.IDisposable par public class MyClass<T> where T : System.IDisposable.
  • Remplacez les noms de types réels par des identificateurs dans les déclarations de paramètres de type (CS0081). Vous devez déclarer des paramètres de type à l’aide d’identificateurs (commeT, ou TKeyTValue) plutôt que de types concrets (comme int ou string). L’objectif d’un paramètre de type est de servir d’espace réservé que le compilateur remplace par des types réels lorsque le type générique ou la méthode est utilisé. Par exemple, remplacez public void F<int>() par public void F<T>().
  • Renommez les paramètres de type, les variables locales ou les paramètres pour éviter les conflits de nommage (CS0412, CS0694). Les noms de paramètres de type ne peuvent pas masquer les identificateurs dans la même étendue. Ils ne peuvent pas correspondre au nom du type ou de la méthode contenant. Ces conflits créent une ambiguïté sur l'identificateur qui est référencé. Par exemple, si vous avez une méthode public void F<T>(), vous ne pouvez pas déclarer une variable double T locale à l’intérieur de cette méthode et vous ne pouvez pas nommer un paramètre de type identique à son type conteneur (class C<C>).
  • Utilisez la syntaxe de déclaration d’enregistrement correcte (CS9012). Lors de la déclaration d’un type d’enregistrement, vous devez utiliser record classrecord struct ou (ou simplement record pour un type référence). Le record mot clé seul ne peut pas apparaître dans des positions où le compilateur attend une syntaxe de déclaration de type. Par exemple, si vous vouliez déclarer un type d’enregistrement, écrivez record class MyRecord ou record struct MyRecord, plutôt que d’utiliser record où un mot clé différent est attendu.

Pour plus d’informations, consultez Paramètres de type générique et génériques.

Déclaration et ordonnancement des contraintes

Les erreurs suivantes concernent la syntaxe et l’ordre des contraintes sur les paramètres de type générique :

  • CS0401 : La new() contrainte doit être la dernière contrainte spécifiée.
  • CS0449 : Les contraintes class, struct, unmanaged, notnull et default ne peuvent pas être combinées ou dupliquées, et doivent être spécifiées en premier dans la liste des contraintes.
  • CS0450 : Paramètre de type : ne peut pas spécifier à la fois une classe de contrainte et la contrainte class ou struct.
  • CS0451 : La new() contrainte ne peut pas être utilisée avec la struct contrainte.
  • CS9011 : Le mot clé delegate ne peut pas être utilisé comme contrainte. Tu veux dire System.Delegate?

Les contraintes sur les paramètres de type doivent suivre un ordre spécifique : les contraintes primaires (class, struct, , unmanagednotnullou default) viennent en premier, suivies des contraintes d’interface ou de classe, et enfin la contrainte du new() constructeur. Certaines contraintes s’excluent mutuellement et ne peuvent pas être combinées.

Pour corriger ces erreurs :

  • Placez la new() contrainte à la fin de la liste de contraintes (CS0401). La new() contrainte doit apparaître après toutes les autres contraintes. Par exemple, remplacez where T : new(), IDisposable par where T : IDisposable, new().
  • Placez d’abord les contraintes primaires et ne combinez pas les contraintes mutuellement exclusives (CS0449). Vous pouvez spécifier au maximum l'un des class, struct, unmanaged, notnull ou default, et il doit apparaître en premier dans la liste de contraintes. Les contraintes class et struct sont mutuellement exclusives, tout comme class et unmanaged. Dans un contexte nullable, class implique notnulldéjà , de sorte qu’ils ne peuvent pas être combinés.
  • Ne combinez pas de contrainte de classe spécifique avec struct (CS0450). Si un paramètre de type est limité à un type de classe spécifique, il s’agit implicitement d’un type référence, qui contredit la struct contrainte. Supprimez la contrainte de classe ou la struct contrainte.
  • Ne pas combiner new() avec struct (CS0451). Tous les types valeur (structs) ont implicitement un constructeur sans paramètre public, de sorte que la new() contrainte est redondante lorsqu’elle est combinée avec struct. Supprimez la contrainte lorsque vous utilisez new()struct.
  • Remplacez par delegateSystem.Delegate les clauses de contrainte (CS9011). Le delegate mot clé est utilisé pour déclarer des types délégués, et non comme contrainte. Pour limiter un paramètre de type aux types délégués, utilisez-le System.Delegate comme type de contrainte. Par exemple, remplacez where T : delegate par where T : System.Delegate.

L’exemple suivant montre l’ordre des contraintes correct :

using System;

// Primary constraint first, then interface constraints, then new()
class C<T> where T : class, IDisposable, new() { }

// struct doesn't need new() - it's implicit
class D<T> where T : struct, IComparable { }

// Delegate constraint using System.Delegate
class E<T> where T : System.Delegate { }

Pour plus d’informations, consultez Contraintes sur les paramètres de type.

Nombre d’arguments de type et utilisation

Les erreurs suivantes concernent la fourniture du nombre correct et du type d’arguments de type aux types et méthodes génériques :

  • CS0224 : Une méthode avec vararg ne peut pas être générique, être dans un type générique ou avoir un paramètre params.
  • CS0305 : L’utilisation du type générique nécessite des arguments de type N.
  • CS0306 : Le type peut ne pas être utilisé comme argument de type.
  • CS0307 : L’identificateur n’est pas une méthode générique. Si vous avez prévu une liste d’expressions, utilisez des parenthèses autour de l’expression.
  • CS0308 : Impossible d’utiliser la méthode ou le type non générique avec des arguments de type.
  • CS7002 : Utilisation inattendue d’un nom générique.

Pour corriger ces erreurs, vérifiez que vous fournissez le nombre exact d’arguments de type requis par la déclaration générique. Utilisez uniquement des types valides comme arguments de type. N’appliquez pas d’arguments de type à des constructions non génériques :

  • Supprimez les paramètres de type générique ou contenant des déclarations de type générique des méthodes qui utilisent __arglist (CS0224). Le __arglist mot clé est incompatible avec les génériques, car les mécanismes d’exécution de gestion des listes d’arguments variables sont en conflit avec la substitution de type requise pour les paramètres de type générique. Cette restriction s’applique également au params mot clé lorsqu’il est utilisé en combinaison avec des méthodes génériques ou des méthodes au sein de types génériques.
  • Indiquez le nombre exact d’arguments de type spécifiés dans la déclaration de type ou de méthode générique (CS0305). Chaque paramètre de type générique déclaré dans la définition doit avoir un argument de type correspondant lorsque le type générique est instancié. Le compilateur doit savoir quel type concret remplacer par chaque paramètre de type. Par exemple, si une classe est déclarée en tant que class MyList<T>, vous devez fournir exactement un argument de type lors de son utilisation, par exemple, et MyList<int>non MyList<int, string>.
  • Utilisez uniquement des types valides comme arguments de type (CS0306). Les types de pointeur, tels que int* ou char*, ne peuvent pas être utilisés comme arguments de type, car les types génériques nécessitent des types managés que le garbage collector peut suivre et les types de pointeurs ne sont pas gérés. Si vous devez utiliser des pointeurs dans un contexte générique, envisagez d’utiliser IntPtr ou de restructurer votre code pour éviter de mélanger des génériques avec du code non sécurisé.
  • Supprimez la syntaxe de l'argument de type des constructions non génériques (CS0307, CS0308). Les arguments de type placés entre crochets angle (comme <int>) peuvent uniquement être appliqués aux types et méthodes génériques qui déclarent des paramètres de type. Vous devez supprimer entièrement les arguments de type ou vous assurer que vous avez importé l’espace de noms qui contient la version générique du type. Par exemple, IEnumerator<T> nécessite la directive using System.Collections.Generic;, tandis que IEnumerator est en System.Collections.
  • Supprimez les paramètres de type des déclarations qui ne prennent pas en charge les génériques (CS7002). Certaines constructions, telles que les énumérations, ne peuvent pas être génériques. Si vous avez besoin d’un conteneur générique pour les valeurs d’énumération, envisagez d’utiliser une classe ou un struct générique à la place.

Pour plus d’informations, consultez Paramètres de type générique et génériques.

Contraintes de constructeur

Les erreurs suivantes concernent la contrainte sur les new() paramètres de type générique :

  • CS0304 : Impossible de créer une instance du type de variable, car elle n’a pas la new() contrainte.
  • CS0310 : Le type doit être un type non abstrait avec un constructeur sans paramètre public afin de l’utiliser comme paramètre dans le type générique ou la méthode.
  • CS0417 : Identificateur : ne peut pas fournir d’arguments lors de la création d’une instance d’un type de variable.

Pour corriger ces erreurs, ajoutez la new() contrainte aux paramètres de type qui doivent être instanciés, vérifiez que les arguments de type ont des constructeurs sans paramètre public et évitez de passer des arguments lors de la construction d’instances de paramètres de type :

  • Ajoutez la new() contrainte à la déclaration de paramètre de type (CS0304). Lorsque vous utilisez l’opérateur new pour créer une instance d’un paramètre de type au sein d’un type ou d’une méthode générique, le compilateur doit être en mesure de garantir que tout argument de type fourni au moment de l’exécution a un constructeur sans paramètre disponible. La new() contrainte fournit cette garantie au moment de la compilation, ce qui permet au compilateur de générer le code d’instanciation approprié. Par exemple, si vous avez class C<T> avec un membre T t = new T();, vous devez changer la déclaration en class C<T> where T : new().
  • Vérifiez que les arguments de type utilisés avec new() les paramètres de type contraint ont des constructeurs sans paramètre public (CS0310). Lorsqu’un type ou une méthode générique déclare une new() contrainte sur un paramètre de type, tout type concret utilisé comme argument de type doit être non abstrait et doit fournir un constructeur sans paramètre public. Si un type possède uniquement des constructeurs non publics (tels que private ou protected constructeurs) ou ne possède que des constructeurs avec des paramètres, il ne peut pas satisfaire la new() contrainte. Pour corriger cette erreur, ajoutez un constructeur sans paramètre public au type ou utilisez un argument de type différent qui en a déjà un.
  • Supprimez les arguments du constructeur lors de l’instanciation des paramètres de type (CS0417). La new() contrainte garantit uniquement l’existence d’un constructeur sans paramètre. Vous ne pouvez donc pas passer d’arguments car new T(arguments) le compilateur ne peut pas vérifier qu’un constructeur avec ces types de paramètres spécifiques existe sur les types qui sont remplacés par T. Si vous devez construire des instances avec des arguments spécifiques, envisagez d’utiliser des méthodes de fabrique, des modèles de fabrique abstraits ou des contraintes de classe de base ou d’interface spécifiques qui définissent le comportement de construction dont vous avez besoin.

Pour plus d’informations, consultez Contraintes sur les paramètres de type et la new() contrainte.

Satisfaction des contraintes et conversions

Les erreurs suivantes concernent les arguments de type qui ne satisfont pas aux contraintes des paramètres de type générique :

  • CS0311 : Le type ne peut pas être utilisé comme paramètre T de type dans le type générique ou la méthode. Il n’existe aucune conversion de référence implicite.
  • CS0312 : Le type ne peut pas être utilisé comme paramètre de type dans le type générique ou la méthode. Le type Nullable ne satisfait pas la contrainte.
  • CS0313 : Le type ne peut pas être utilisé comme paramètre de type dans le type générique ou la méthode. Le type Nullable ne satisfait pas la contrainte. Les types nullables ne peuvent pas satisfaire à des contraintes d’interface.
  • CS0314 : Le type ne peut pas être utilisé comme paramètre de type dans le type générique ou dans la méthode. Il n'y a pas de conversion de boxing ou de conversion de type paramétrique.
  • CS0315 : Le type ne peut pas être utilisé en tant que paramètre de type dans le type générique ou la méthode TypeorMethod<T>. Il n’y a pas de conversion boxing.

Pour corriger ces erreurs, utilisez des arguments de type qui répondent à toutes les contraintes par le biais de conversions appropriées, assurez-vous que les classes dérivées répètent les contraintes de classe de base et comprenez que les types de valeurs nullables ont des exigences de contrainte spéciales :

  • Modifiez l’argument de type en un qui a une conversion de référence implicite vers le type de contrainte (CS0311). Lorsqu’un paramètre de type a une contrainte telle que where T : BaseType, tout argument de type doit pouvoir être converti en BaseType par une conversion de référence implicite ou par une conversion d'identité. L’argument de type doit être BaseType lui-même, dériver de BaseType, ou implémenter BaseType s’il s’agit d’une interface. Les conversions numériques implicites (de short à int) ne répondent pas aux contraintes de paramètre de type générique, car ces conversions sont des conversions de valeurs, et non des conversions de référence.
  • Répétez les contraintes de paramètre de type de la classe de base dans toute déclaration de classe dérivée (CS0314). Lorsqu’une classe générique dérivée hérite d’une classe générique de base qui a des contraintes sur ses paramètres de type, la classe dérivée doit déclarer les mêmes contraintes sur ses paramètres de type correspondants. Vous devez répéter ces contraintes, car le compilateur doit vérifier que les arguments de type fournis à la classe dérivée répondent aux exigences de la classe de base. Par exemple, si vous avez public class A<T> where T : SomeClass, toute classe dérivant de celle-ci doit être déclarée en tant que public class B<T> : A<T> where T : SomeClass.
  • Utilisez des types valeur non nullables ou modifiez le type de contrainte (CS0312, CS0313). Les types valeur nullables (par exemple int?) sont distincts de leurs types valeur sous-jacents et ne répondent pas aux mêmes contraintes. Il n’existe aucune conversion implicite entre int? et int, et les types valeur nullable ne peuvent pas satisfaire aux contraintes d’interface, car le wrapper nullable lui-même n’implémente pas l’interface, même si le type de valeur sous-jacent le fait. Pour corriger ces erreurs, utilisez la forme non nullable du type valeur comme argument de type, ou ajustez votre contrainte pour accepter object ou un type de référence nullable le cas échéant.
  • Vérifiez que les arguments de type répondent aux contraintes de type de référence ou de classe (CS0315). Lorsqu’un paramètre de type est limité à un type de classe (par exemple where T : SomeClass), vous ne pouvez pas utiliser de type valeur (struct) comme argument de type, car il n’existe aucune conversion de boxing qui satisfait à la relation de contrainte. La contrainte nécessite un type de référence qui a une relation d’héritage ou d’implémentation avec le type de contrainte. Pour résoudre cette erreur, remplacez le struct par une classe si elle est sémantiquement appropriée, ou supprimez la contrainte de classe si le type générique peut fonctionner avec des types valeur.

Pour plus d’informations, consultez Contraintes sur les paramètres de type et conversions implicites.

Restrictions d’utilisation de type générique

Les erreurs suivantes concernent les restrictions relatives à l’utilisation des types génériques :

  • CS0403 : Impossible de convertir null en paramètre de type, car il peut s’agir d’un type valeur non nullable. Envisagez plutôt d’utiliser default(T) .
  • CS0413 : Le paramètre de type ne peut pas être utilisé avec l’opérateur as , car il n’a pas de contrainte de type de classe ni de class contrainte.
  • CS0695 : Le type ne peut pas implémenter à la fois les deux interfaces, car elles peuvent se confondre pour certaines substitutions de paramètres de type.
  • CS0698 : un type générique ne peut pas dériver du type, car il s’agit d’une classe d’attributs.
  • CS8322 : Impossible de passer un argument avec un type dynamique à une fonction locale générique avec des arguments de type déduits.
  • CS9338 : Accessibilité incohérente : le type est moins accessible que la classe.

Pour corriger ces erreurs, utilisez default plutôt que null pour les paramètres de type non contraints, ajoutez des contraintes de classe lors de l’utilisation de l’opérateur as, évitez les conflits d’unification d’interface, ne créez pas de classes d'attribut générique, et assurez-vous que les arguments de type correspondent à la visibilité de leurs membres hôtes :

  • Remplacez null les affectations par default(T) ou ajoutez une class contrainte (CS0403). Lorsque vous attribuez null un paramètre de type non contrainte, le compilateur ne peut pas garantir que l’argument de type est un type de référence qui accepte des null valeurs, car il peut s’agir d’un type valeur comme int ou struct, qui ne peut pas être null. Pour résoudre cette erreur, utilisez default(T), qui fournit la valeur par défaut appropriée pour n’importe quel type (null pour les types référence, zéro ou vide pour les types valeur), ou ajoutez une class contrainte au paramètre de type si vous avez spécifiquement besoin d’une sémantique de type référence et souhaitez autoriser null les affectations.
  • Ajoutez une class contrainte de type ou spécifique lors de l’utilisation de l’opérateur as (CS0413). L’opérateur as effectue un cast de type sécurisé qui retourne null si la conversion échoue, mais ce comportement est incompatible avec les types valeur, car les types valeur ne peuvent pas être null. Lorsque vous utilisez as un paramètre de type non contrainte, le compilateur ne peut pas garantir que l’argument de type n’est pas un type valeur. Il rejette donc le code. Pour corriger cette erreur, ajoutez une class contrainte ou une contrainte de type référence spécifique (par where T : SomeClassexemple) pour vous assurer que le paramètre de type est toujours un type de référence capable de gérer correctement le null résultat d’un cast ayant échoué.
  • Évitez d’implémenter la même interface générique plusieurs fois avec des paramètres de type qui pourraient unifier (CS0695). Lorsqu’une classe implémente une interface générique plusieurs fois avec différents paramètres de type (par exemple class G<T1, T2> : I<T1>, I<T2>), il existe un risque que quelqu’un puisse l’instancier avec le même type pour les deux paramètres (G<int, int>), ce qui créerait un conflit, car la classe implémenterait effectivement I<int> deux fois. Pour résoudre cette erreur, implémentez l’interface une seule fois, restructurez vos paramètres de type pour empêcher l’unification ou utilisez des classes non génériques distinctes pour différentes spécialisations.
  • Supprimez les paramètres de type générique des classes d’attributs (CS0698).

    Note

    Cette erreur n’est pas générée dans les versions actuelles de C#, car les attributs génériques sont désormais pris en charge.

  • Spécifiez explicitement des arguments de type lors de la transmission de valeurs dynamiques à des fonctions locales génériques (CS8322). Lorsque vous passez un dynamic argument à une fonction locale générique, le compilateur ne peut pas déduire les arguments de type, car le type réel n’est pas connu tant que l’exécution n’est pas terminée. Pour corriger cette erreur, spécifiez explicitement l’argument de type (par exemple, LocalFunc<int>(d)), convertissez la valeur dynamique en type attendu ou utilisez une variable non dynamique.
  • Vérifiez que les arguments de type utilisés dans les signatures publiques ou protégées sont au moins aussi accessibles que le membre qui les utilise (CS9338). Un membre générique public ou protégé doit utiliser des arguments de type accessibles publiquement. Sinon, le code externe n’a pas pu référencer ou utiliser correctement la signature du membre. Par exemple, si vous avez public class Container<T>T est un type interne, les assemblies externes peuvent voir le Container mais ne peuvent pas bien fonctionner avec lui car elles ne peuvent pas voir T. Pour corriger cette erreur, rendez l'argument de type public ou réduisez l'accessibilité du membre pour qu'elle corresponde à celle de l'argument de type.

Pour plus d’informations, consultez Contraintes sur les paramètres de type, les expressions de valeur par défaut et les attributs.

Types de contraintes valides

Les erreurs suivantes concernent l’utilisation de types non valides comme contraintes sur les paramètres de type générique :

  • CS0405 : Contrainte dupliquée pour le paramètre de type.
  • CS0702 : La contrainte ne peut pas être une classe spéciale.
  • CS0703 : Accessibilité incohérente : le type de contrainte est moins accessible que la déclaration.
  • CS0706 : Type de contrainte non valide. Un type utilisé comme contrainte doit être une interface, une classe non scellée ou un paramètre de type.
  • CS0717 : static class: les classes statiques ne peuvent pas être utilisées comme contraintes.

Une contrainte doit être une interface, une classe non scellée ou un paramètre de type. Certains types ne sont pas valides en tant que contraintes en raison de leur signification particulière dans le système de type .NET ou parce qu’ils ne peuvent pas être hérités.

Pour corriger ces erreurs :

  • Supprimez les contraintes dupliquées (CS0405). Chaque contrainte ne peut apparaître qu’une seule fois dans une clause de contrainte. Si vous avez where T : I, I, supprimez le doublon.
  • N’utilisez pas de classes spéciales comme contraintes (CS0702). Les types Object, Arrayet ValueType ne peuvent pas être utilisés comme contraintes. Chaque type dérive déjà de Object, donc la restreindre n'apporte aucune valeur. Array et ValueType sont des types de base abstraits qui ne peuvent pas être directement hérités. Si vous avez besoin d’un comportement de type tableau, utilisez IList<T> ou IEnumerable<T> à la place.
  • Vérifiez que les types de contraintes sont au moins aussi accessibles que le type générique (CS0703). Un type générique public ne peut pas avoir de contraintes à l’aide de types internes, car le code externe ne peut pas fournir d’arguments de type valides. Rendre le type de contrainte public ou réduire l’accessibilité du type générique.
  • Utilisez uniquement des interfaces, des classes non scellées ou des paramètres de type en tant que contraintes (CS0706). Vous ne pouvez pas utiliser de tableaux, de classes scellées, de structs, d’énumérations ou d’autres types non valides comme contraintes. Si vous avez besoin d’un comportement spécifique, envisagez d’utiliser une interface que les types souhaités implémentent.
  • N’utilisez pas de classes statiques comme contraintes (CS0717). Les classes statiques ne peuvent pas être étendues, car elles contiennent uniquement des membres statiques. Aucun type ne peut exister qui dérive d’une classe statique, ce qui le rend inutile en tant que contrainte. Utilisez plutôt une classe ou une interface non statique.

L’exemple suivant montre les types de contraintes valides :

public interface IMyInterface { }
public class MyBaseClass { }

// Valid: interface constraint
class A<T> where T : IMyInterface { }

// Valid: non-sealed class constraint
class B<T> where T : MyBaseClass { }

// Valid: type parameter constraint
class C<T, U> where T : U { }

Pour plus d’informations, consultez Contraintes sur les paramètres de type.

Conflits de contraintes et dépendances circulaires

Les erreurs suivantes concernent les conflits entre les contraintes ou les dépendances circulaires dans les déclarations de contrainte :

  • CS0454 : dépendance de contrainte circulaire impliquant le paramètre de type 1 et le paramètre de type 2.
  • CS0455 : Le paramètre de type hérite des contraintes conflictuelles.

Les contraintes ne peuvent pas créer de dépendances circulaires et les paramètres de type ne peuvent pas hériter de contraintes conflictuelles impossibles à satisfaire simultanément.

Pour corriger ces erreurs :

  • Supprimez les dépendances de contrainte circulaire (CS0454). Un paramètre de type ne peut pas dépendre directement ou indirectement de lui-même par ses contraintes. Par exemple, where T : U where U : T crée une dépendance circulaire, car T dépend U et U dépend Tde . Arrêtez le cycle en supprimant l’une des contraintes.
  • Supprimez les contraintes héritées en conflit (CS0455). Un paramètre de type ne peut pas être contraint à plusieurs classes non liées, car C# ne prend pas en charge l’héritage de plusieurs classes. De même, il ne peut pas être contraint à la fois à struct et à un type de classe, car ces contraintes s’excluent mutuellement. Restructurez votre hiérarchie de type ou supprimez l’une des contraintes en conflit.

L’exemple suivant montre les problèmes :

// CS0454: Circular dependency - T depends on U and U depends on T
class Circular<T, U> where T : U where U : T { }

// CS0455: Conflicting constraints - U can't derive from both B and B2
public class B { }
public class B2 { }
public class G<T> where T : B
{
    public class N<U> where U : B2, T { }
}

Pour plus d’informations, consultez Contraintes sur les paramètres de type.

Variance des paramètres de type

L’erreur suivante concerne les modificateurs de variance sur les paramètres de type générique :

  • CS1961 : Variance non valide : le paramètre de type doit être validement variant sur le type.

Les modificateurs de variance (in pour contravariance, out pour covariance) contrôlent la façon dont vous utilisez les paramètres de type dans les déclarations d’interface et de délégué. Un paramètre de type covariant (out) ne peut apparaître que dans les positions de sortie (types de retour), tandis qu’un paramètre de type contravariant (in) ne peut apparaître que dans les positions d’entrée (types de paramètres).

Pour corriger cette erreur :

  • Utilisez out (covariant) pour les paramètres de type qui apparaissent uniquement dans les types de retour. La covariance permet d’utiliser un type plus dérivé où un type moins dérivé est attendu.
  • Utilisez in (contravariant) pour les paramètres de type qui apparaissent uniquement dans les types de paramètres. La contravariance permet d’utiliser un type moins dérivé où un type plus dérivé est attendu.
  • Supprimez le modificateur de variance si le paramètre de type doit apparaître à la fois dans les positions d’entrée et de sortie.

L’exemple suivant montre une utilisation correcte et incorrecte de la variance :

// Incorrect: out T can't appear in input position
interface IWrong<out T>
{
    void Method(T arg);  // CS1961
}

// Correct: out T only in output positions
interface ICovariant<out T>
{
    T GetValue();
}

// Correct: in T only in input positions
interface IContravariant<in T>
{
    void Process(T arg);
}

// No modifier needed for both input and output
interface IInvariant<T>
{
    T Transform(T arg);
}

Pour plus d’informations, consultez Covariance et Contravariance dans les génériques.