Проблемы контравариантности с вложенными интерфейсами - PullRequest
0 голосов
/ 22 февраля 2019
interface IModel
{ 
}

class ModelA : IModel
{
}

interface IService<T> where T: IModel
{
}

class ServiceA : IService<ModelA>
{
}

Учитывая приведенное выше определение классов и интерфейсов, работает следующее:

IModel model = new ModelA();

Указывает, что ModelA может быть приведен к его интерфейсу IModel

Следующеетакже работает:

IService<ModelA> service1 = new ServiceA();

Указывает, что ServiceA может быть приведен к его интерфейсу IService<ModelA>

Однако происходит следующее:

IService<IModel> service2 = new ServiceA();

Сообщение об ошибкеговорит, что ServiceA нельзя неявно преобразовать в IService<IModel>

Я удивлен этим, поскольку:
ModelA можно преобразовать в IModel, а
ServiceA можно преобразоватьна IService<IModel>
я ожидал, что произойдет следующее:
ServiceA -> IService<ModelA> -> IService<IModel>

Но это не представляется возможным.

У кого-нибудь есть объяснение, почему это так?

1 Ответ

0 голосов
/ 22 февраля 2019

Единственный реальный вариант, который у вас есть, это применить модификатор out к универсальному типу IService, делая его Ковариант

Ковариация позволяет использоватьболее производный тип, чем тот, который задан универсальным параметром

interface IService<out T> where T : IModel
{
}

out (универсальный модификатор) (C # Reference)


Чтобы быть конкретным,Насколько это похоже, IService<IModel> - это не то же самое, что означает ServiceA : IService<ModelA>

out (грубо говоря), он может появляться только в выходных позициях.

Имейте в виду, что это серьезно ограничит то, что вы можете сделать с T.

Если вам нужно использовать T в IService (а это не просто возврат метода в IService), тогда вам может понадобиться object или переосмыслить проблему

...