Общий C # «где ограничение» с определением «любого универсального типа»?

113

Приведу пример:

  1. У меня есть определение общего класса / интерфейса:

    interface IGenericCar< T > {...}

  2. У меня есть другой класс / интерфейс, который я хочу связать с классом выше, например:

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

По сути, я хочу, чтобы мой общий IGarrage зависел от него IGenericCar, независимо от того, является он IGenericCar<int>или IGenericCar<System.Color>, потому что у меня нет никакой зависимости от этого типа.

Ненад
источник

Ответы:

142

Обычно есть 2 способа добиться этого.

Вариант 1 : добавьте еще один параметр для IGarrageпредставления, Tкоторый должен быть передан в IGenericCar<T>ограничение:

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

Вариант 2 : определить базовый интерфейс, для IGenericCar<T>которого не является универсальным, и ограничить этот интерфейс

interface IGenericCar { ... }
interface IGenericCar<T> : IGenericCar { ... }
interface IGarrage<TCar> where TCar : IGenericCar { ... }
JaredPar
источник
6
Хорошо, но что мне делать, если мне нужно использовать свой общий тип Tвнутри IGarage<TCar>? Я не вижу возможности в варианте 2. Лучшим решением было бы IGarage<TCar>найти тип Tпутем анализа типа TCar.
pt12lol
2
Для потомков МОЖЕТ быть создан тип, который имеет параметр типа необработанного универсального типа, но только с отражением во время выполнения, и созданный класс никогда не может быть создан, потому что необработанный параметр универсального типа никогда не может быть создан автоматически без полного определения соответствующего параметра типа ЕГО. Я не вижу, где это может быть полезно, за исключением случаев, когда суперобобщенные статические члены самого внешнего класса (то есть IGarage<IGenericCar<?>>.TellMeAboutCarsInGeneral(), что, вероятно, было бы результатом плохого дизайна), но я сделал это в своей работе, и это возможно.
Майкл Хоффманн
Я предполагаю, что любой может добавить интерфейс IGenericCar к классу и разбить ограниченный метод неожиданным классом.
N-ate
2
@ pt12lol: если на IGarrage<TCar>самом деле обрабатывает базовый универсальный тип (например, он обрабатывает свойство указанного типа), то ему необходимо знать тип, который требует, чтобы вы указали тип, который является вариантом 1 (тогда единственный жизнеспособный вариант). Однако, если IGarrage<TCar>не обрабатывает непосредственно базовый универсальный тип (весь IGarrage<TCar>код не зависит от этого базового типа), то допустим вариант 2.
Flater
6

Имеет ли смысл делать что-то вроде:

interface IGenericCar< T > {...}
interface IGarrage< TCar, TCarType > 
    where TCar: IGenericCar< TCarType > {...}
рычать
источник