Richard Deeming
Ковариация и Контравариация в универсальных шаблонах | Майкрософт документы[^]
Это не простая тема. :)
Представьте себе мир, где I<Derived>
был эквивалентен I<Base>
Это означало бы, что следующий код будет работать:
class Base { }
class Derived : Base { }
class OtherDerived : Base { }
List<Derived> list = new List<Derived>();
IList<Base> baseList = list;
baseList.Add(new OtherDerived());
Теперь список разбит - он может содержать только
Derived
объекты, но нам удалось прокрасться
OtherDerived
пример в него.
Для того чтобы ваш образец работал, ваш
ITest<T>
интерфейс должен быть ковариантным:
interface ITest<out T> where T : class, IBaseObject
{
}
С этим единственным изменением ваш код будет работать так, как ожидалось.
Однако теперь ваш интерфейс будет подчиняться ограничениям, наложенным на ковариантный интерфейс: вы не можете использовать параметр type в качестве параметра метода, даже если он не является параметром метода.
out
параметр; вы также не можете использовать его в качестве типа записываемого свойства.
csrss
Таким образом, кажется, что я не могу использовать текущий дизайн, потому что интерфейс (ITest) использует T как in, так и out. Спасибо
Richard Deeming
В зависимости от того, как вы его используете и что собираетесь с ним делать. ITest<Base>
, вы вероятно быть в состоянии разделить интерфейс на две или, возможно, три части: ковариантную часть, контравариантную часть и инвариантную часть.
Например, IReadOnlyList<T>[^] предоставляет ковариантную версию IList<T>[^] интерфейс.
csrss
Ричард, большое тебе спасибо :)
Я действительно немного изменил свой дизайн, введя дополнительный не универсальный интерфейс, и это решило проблему.