C # rodzajowy „gdzie ograniczenie” z definicją „dowolnego typu ogólnego”?

113

Podam przykład:

  1. Mam ogólną definicję klasy / interfejsu:

    interface IGenericCar< T > {...}

  2. Mam inną klasę / interfejs, który chcę powiązać z klasą powyżej, na przykład:

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

Zasadniczo chcę, aby mój ogólny IGarrage był zależny IGenericCar, niezależnie od tego, czy jest, IGenericCar<int>czy IGenericCar<System.Color>, ponieważ nie mam żadnej zależności od tego typu.

Nenad
źródło

Odpowiedzi:

142

Zwykle można to osiągnąć na dwa sposoby.

Opcja 1 : Dodaj kolejny parametr do IGarragereprezentowania tego, Tktóry powinien zostać przekazany do IGenericCar<T>ograniczenia:

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

Opcja 2 : Zdefiniuj interfejs podstawowy, dla IGenericCar<T>którego nie jest ogólny i ogranicz go do tego interfejsu

interface IGenericCar { ... }
interface IGenericCar<T> : IGenericCar { ... }
interface IGarrage<TCar> where TCar : IGenericCar { ... }
JaredPar
źródło
6
Ok, ale co powinienem zrobić, jeśli muszę użyć mojego typu ogólnego Tw IGarage<TCar>? Nie widzę żadnej możliwości w opcji 2. Najlepszym rozwiązaniem byłoby IGarage<TCar>znalezienie typu Tpoprzez analizę typu TCar.
pt12lol
2
Dla potomności MOŻE zostać utworzony typ, który ma parametr typu surowego typu ogólnego, ale tylko z odbiciem w czasie wykonywania, a utworzona klasa nigdy nie może zostać skonstruowana, ponieważ surowego parametru typu ogólnego nigdy nie można skonstruować automatycznie bez pełnej definicji odpowiedniego parametru typu ITS. Nie widzę, gdzie to mogłoby się przydać, z wyjątkiem przypadków, w których super-ogólne statyczne elementy składowe najbardziej zewnętrznej klasy (tj. IGarage<IGenericCar<?>>.TellMeAboutCarsInGeneral(), Co prawdopodobnie byłoby wynikiem złego projektu), ale zrobiłem to podczas majsterkowania i jest możliwe.
Michael Hoffmann
Zakładam, że każdy może dodać interfejs IGenericCar do klasy i przerwać metodę z ograniczeniami za pomocą nieoczekiwanej klasy.
N-zjadł
2
@ pt12lol: Jeśli IGarrage<TCar>faktycznie obsługuje podstawowy typ ogólny (np. obsługuje właściwość wspomnianego typu), to musi znać typ, co wymaga określenia typu, czyli opcji 1 (wówczas jedyna możliwa opcja). Jeśli jednak IGarrage<TCar>nie obsługuje bezpośrednio podstawowego typu ogólnego (cały IGarrage<TCar>kod jest agnostyczny dla tego typu podstawowego), wówczas opcja 2 jest prawidłowa.
Flater
6

Czy miałoby sens zrobienie czegoś takiego:

interface IGenericCar< T > {...}
interface IGarrage< TCar, TCarType > 
    where TCar: IGenericCar< TCarType > {...}
warkocz
źródło