嵌套接口的逆变问题

Ara*_*h-s 1 .net c# generics contravariance nested-generics

interface IModel
{ 
}

class ModelA : IModel
{
}

interface IService<T> where T: IModel
{
}

class ServiceA : IService<ModelA>
{
}
Run Code Online (Sandbox Code Playgroud)

鉴于上面的类和接口的定义,以下工作:

IModel model = new ModelA();
Run Code Online (Sandbox Code Playgroud)

表明ModelA可以强制转换为其接口IModel

以下也适用:

IService<ModelA> service1 = new ServiceA();
Run Code Online (Sandbox Code Playgroud)

表明ServiceA可以强制转换为其接口IService<ModelA>

但是,以下情况会失败:

IService<IModel> service2 = new ServiceA();
Run Code Online (Sandbox Code Playgroud)

错误消息表明ServiceA不能隐式转换为IService<IModel>

我对此感到惊讶,因为:
ModelA可以转换为IModel,并且
ServiceA可以转换为IService<IModel>
我期望发生以下情况:
ServiceA-> IService<ModelA>->IService<IModel>

但这似乎不可能。

有人能解释为什么吗?

AAA*_*ddd 5

这里唯一真正的选择是out对泛型类型应用修饰符,IService使其成为协变的

协方差使您能够使用比泛型参数指定的派生类型更多的类型

interface IService<out T> where T : IModel
{
}
Run Code Online (Sandbox Code Playgroud)

out(通用修饰符)(C# 参考)


具体来说,尽管看起来IService<IModel>ServiceA : IService<ModelA>

out意思是(粗略地说),它只能出现在输出位置。

但请注意,这将严重限制您可以使用T.

如果您需要使用Tin IService(并且它不仅仅是 in 方法的返回IService),那么您可能需要使用object或重新考虑问题。