C # generico "vincolo dove" con "qualsiasi tipo generico" definizione?


113

Faccio un esempio:

  1. Ho una definizione generica di classe / interfaccia:

    interface IGenericCar< T > {...}

  2. Ho un'altra classe / interfaccia che voglio mettere in relazione con la classe sopra, ad esempio:

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

Fondamentalmente, voglio che il mio IGarrage generico dipenda da IGenericCar, indipendentemente dal fatto che sia IGenericCar<int>o IGenericCar<System.Color>, perché non ho alcuna dipendenza da quel tipo.

Risposte:


142

Ci sono in genere 2 modi per ottenere questo risultato.

Opzione 1 : aggiungi un altro parametro per IGarragerappresentare il Tche dovrebbe essere passato nel IGenericCar<T>vincolo:

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

Opzione 2 : definire un'interfaccia di base per la IGenericCar<T>quale non è generica e vincolare tale interfaccia

interface IGenericCar { ... }
interface IGenericCar<T> : IGenericCar { ... }
interface IGarrage<TCar> where TCar : IGenericCar { ... }

6
Ok, ma cosa devo fare se devo utilizzare il mio tipo generico Tall'interno del IGarage<TCar>? Non vedo alcuna possibilità nell'opzione2. La soluzione migliore sarebbe se si IGarage<TCar>trovasse il tipo Tanalizzando il tipo TCar.
pt12lol

2
Per i posteri, può essere creato un tipo che ha un parametro di tipo di un tipo generico grezzo, ma solo con la riflessione in fase di esecuzione, e la classe creata non potrebbe mai essere costruita, perché il parametro di tipo generico grezzo non potrebbe mai essere costruito automaticamente senza una definizione completa del suo rispettivo parametro di tipo. Non vedo dove questo potrebbe essere utile, tranne nei casi in cui membri statici super-generici della classe più esterna (cioè IGarage<IGenericCar<?>>.TellMeAboutCarsInGeneral(), che probabilmente sarebbe il risultato di una cattiva progettazione), ma l'ho fatto nel mio armeggiare, e è possibile.
Michael Hoffmann

Presumo che chiunque possa aggiungere l'interfaccia IGenericCar a una classe e rompere il metodo vincolato con una classe inaspettata.
N-mangiato

2
@ pt12lol: se IGarrage<TCar>gestisce effettivamente il tipo generico sottostante (ad esempio, gestisce una proprietà di detto tipo), allora ha bisogno di conoscere il tipo, il che richiede di specificare il tipo, che è l'opzione 1 (l'unica opzione valida quindi). Tuttavia, se IGarrage<TCar>non gestisce direttamente il tipo generico sottostante (tutto il IGarrage<TCar>codice è indipendente da questo tipo sottostante), l'opzione 2 è valida.
Flater

6

Avrebbe senso fare qualcosa come:

interface IGenericCar< T > {...}
interface IGarrage< TCar, TCarType > 
    where TCar: IGenericCar< TCarType > {...}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.