¿C # genérico "donde restricción" con "cualquier tipo genérico" definición?

113

Déjame dar un ejemplo:

  1. Tengo una definición genérica de clase / interfaz:

    interface IGenericCar< T > {...}

  2. Tengo otra clase / interfaz que quiero relacionar con la clase anterior, por ejemplo:

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

Básicamente, quiero que mi IGarrage genérico dependa de IGenericCar, independientemente de si es IGenericCar<int>o IGenericCar<System.Color>, porque no tengo ninguna dependencia de ese tipo.

Nenad
fuente

Respuestas:

142

Por lo general, hay 2 formas de lograrlo.

Option1 : agregue otro parámetro para IGarragerepresentar el Tque se debe pasar a la IGenericCar<T>restricción:

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

Opción 2 : Defina una interfaz base para la IGenericCar<T>que no sea genérica y restrinja esa interfaz

interface IGenericCar { ... }
interface IGenericCar<T> : IGenericCar { ... }
interface IGarrage<TCar> where TCar : IGenericCar { ... }
JaredPar
fuente
6
Ok, pero ¿qué debo hacer si necesito usar mi tipo genérico Tdentro del IGarage<TCar>? No veo ninguna posibilidad en la opción 2. La mejor solución sería si se IGarage<TCar>encontrara el tipo Tanalizando el tipo TCar.
pt12lol
2
Para la posteridad, se PUEDE crear un tipo que tenga un parámetro de tipo de un tipo genérico sin procesar, pero solo con reflexión en tiempo de ejecución, y la clase creada nunca podría construirse, porque el parámetro de tipo genérico sin procesar nunca podría construirse automáticamente sin una definición completa de su parámetro de tipo respectivo. No veo dónde esto podría ser útil, excepto en los casos en que los miembros estáticos supergenéricos de la clase más externa (es decir IGarage<IGenericCar<?>>.TellMeAboutCarsInGeneral(), que probablemente sería el resultado de un diseño deficiente), pero lo he hecho en mis retoques, y es posible.
Michael Hoffmann
Supongo que cualquiera puede agregar la interfaz IGenericCar a una clase y romper el método restringido con una clase inesperada.
N-ate el
2
@ pt12lol: Si IGarrage<TCar>realmente maneja el tipo genérico subyacente (por ejemplo, maneja una propiedad de dicho tipo), entonces necesita saber el tipo, lo que requiere que especifique el tipo, que es la opción 1 (la única opción viable entonces). Sin embargo, si IGarrage<TCar>no maneja directamente el tipo genérico subyacente (todo el IGarrage<TCar>código es independiente de este tipo subyacente), la opción 2 es válida.
Flater
6

¿Tendría algún sentido hacer algo como:

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