C # genérico “where constraint” com definição de “qualquer tipo genérico”?

113

Deixe-me dar um exemplo:

  1. Tenho algumas definições genéricas de classe / interface:

    interface IGenericCar< T > {...}

  2. Tenho outra classe / interface que quero relacionar com a classe acima, por exemplo:

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

Basicamente, quero que meu IGarrage genérico seja dependente IGenericCar, independentemente de ser IGenericCar<int>ou IGenericCar<System.Color>, porque não tenho nenhuma dependência desse tipo.

Nenad
fonte

Respostas:

142

Normalmente, existem 2 maneiras de fazer isso.

Opção1 : adicione outro parâmetro para IGarragerepresentar o Tque deve ser passado para a IGenericCar<T>restrição:

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

Opção 2 : definir uma interface de base para a IGenericCar<T>qual não é genérica e restringir essa interface

interface IGenericCar { ... }
interface IGenericCar<T> : IGenericCar { ... }
interface IGarrage<TCar> where TCar : IGenericCar { ... }
JaredPar
fonte
6
Ok, mas o que devo fazer se precisar usar meu tipo genérico Tdentro do IGarage<TCar>? Não consigo ver nenhuma possibilidade na opção2. A melhor solução seria IGarage<TCar>encontrar o tipo Tanalisando o tipo TCar.
pt12lol
2
Para a posteridade, um tipo PODE ser criado com um parâmetro de tipo de um tipo genérico bruto, mas apenas com reflexão em tempo de execução, e a classe criada nunca poderia ser construída, porque o parâmetro de tipo genérico bruto nunca poderia ser construído automaticamente sem uma definição completa do respectivo parâmetro de tipo ITS. Não vejo onde isso poderia ser útil, exceto nos casos em que membros estáticos supergenéricos da classe mais externa (ou seja IGarage<IGenericCar<?>>.TellMeAboutCarsInGeneral(), o que provavelmente seria o resultado de um design ruim), mas fiz isso em meus ajustes, e é possível.
Michael Hoffmann
Presumo que qualquer um pode adicionar a interface IGenericCar a uma classe e quebrar o método restrito com uma classe inesperada.
N-ate
2
@ pt12lol: Se IGarrage<TCar>realmente lida com o tipo genérico subjacente (por exemplo, lida com uma propriedade desse tipo), então ele precisa saber o tipo, o que requer que você especifique o tipo, que é a opção 1 (a única opção viável então). No entanto, se IGarrage<TCar>não tratar diretamente o tipo genérico subjacente (todo o IGarrage<TCar>código é agnóstico desse tipo subjacente), a opção 2 é válida.
Dia
6

Faria algum sentido fazer algo como:

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