C # générique «contrainte where» avec la définition «any generic type»?

113

Laissez-moi donner un exemple:

  1. J'ai une définition générique de classe / interface:

    interface IGenericCar< T > {...}

  2. J'ai une autre classe / interface que je souhaite associer à la classe ci-dessus, par exemple:

    interface IGarrage< TCar > : where TCar: IGenericCar< (**any type here**) > {...}

Fondamentalement, je veux que mon IGarrage générique dépende IGenericCar, peu importe si c'est IGenericCar<int>ou IGenericCar<System.Color>, parce que je n'ai aucune dépendance à ce type.

Nenad
la source

Réponses:

142

Il existe généralement 2 façons d'y parvenir.

Option1 : Ajoutez un autre paramètre pour IGarragereprésenter le Tqui doit être passé dans la IGenericCar<T>contrainte:

interface IGarrage<TCar,TOther> where TCar : IGenericCar<TOther> { ... }

Option 2 : définir une interface de base pour IGenericCar<T>laquelle n'est pas générique et contraindre cette interface

interface IGenericCar { ... }
interface IGenericCar<T> : IGenericCar { ... }
interface IGarrage<TCar> where TCar : IGenericCar { ... }
JaredPar
la source
6
Ok, mais que dois-je faire si je dois utiliser mon type générique Tdans le IGarage<TCar>? Je ne vois aucune possibilité dans l'option 2. La meilleure solution serait de IGarage<TCar>trouver le type Ten analysant le type TCar.
pt12lol
2
Pour la postérité, un type PEUT être créé avec un paramètre de type d'un type générique brut, mais uniquement avec réflexion à l'exécution, et la classe créée ne pourrait jamais être construite, car le paramètre de type générique brut ne pourrait jamais être construit automatiquement sans une définition complète du paramètre de type respectif de l'ITS. Je ne vois pas où cela pourrait être utile, sauf dans les cas où des membres statiques super-génériques de la classe la plus externe (c'est IGarage<IGenericCar<?>>.TellMeAboutCarsInGeneral()-à- dire , ce qui serait probablement le résultat d'une mauvaise conception), mais je l'ai fait dans mon bricolage, et il est possible.
Michael Hoffmann
Je suppose que n'importe qui peut ajouter l'interface IGenericCar à une classe et casser la méthode contrainte avec une classe inattendue.
N-mangé
2
@ pt12lol: Si IGarrage<TCar>réellement gère le type générique sous-jacent (par exemple, il gère une propriété dudit type), alors il doit connaître le type, ce qui vous oblige à spécifier le type, qui est l'option 1 (la seule option viable alors). Cependant, si IGarrage<TCar>ne gère pas directement le type générique sous-jacent (tout le IGarrage<TCar>code est indépendant de ce type sous-jacent), alors l'option 2 est valide.
Flater
6

Serait-il logique de faire quelque chose comme:

interface IGenericCar< T > {...}
interface IGarrage< TCar, TCarType > 
    where TCar: IGenericCar< TCarType > {...}
snarf
la source