C# 理解非法泛型转换

C# 理解非法泛型转换,c#,.net,generics,casting,C#,.net,Generics,Casting,我很难理解为什么我正在执行的强制转换会抛出运行时异常,声明这是非法强制转换。我做了一些研究并发现了一些问题,这就引出了MSDN文章。然而,我仍然有点困惑,所以如果有人能帮助澄清,我将不胜感激 以下是两种类类型的对象层次结构: IMongoEntity (interface) | - MongoEntity (abstract) | | -SalesProject (concrete) | | -ManagementProject (concrete)

我很难理解为什么我正在执行的强制转换会抛出运行时异常,声明这是非法强制转换。我做了一些研究并发现了一些问题,这就引出了MSDN文章。然而,我仍然有点困惑,所以如果有人能帮助澄清,我将不胜感激

以下是两种类类型的对象层次结构:

IMongoEntity (interface)
  |   - MongoEntity (abstract)
  |     |    -SalesProject (concrete)
  |     |    -ManagementProject (concrete)

既然这两个服务都派生自相同的接口&抽象类,并且使用的类型参数派生自相同的抽象类,那么为什么这种强制转换是非法的

注意:我对此有解决办法,所以我不是真的在寻找解决方案,而是想了解为什么不允许这样做。

MyType
MyType
没有任何继承关系,即使
Derived
派生自
Base
。这两种泛型类型只是两种不同的类型

解决此问题的一种方法是使用非通用接口作为基本接口:

public interface IEntityService
{
    void DoSomething(object item);
}

public interface IEntityService<T> : IEntityService
{
    void DoSomething(T item);
}
公共接口IEntityService
{
无效剂量测定(目标项目);
}
公共接口IEntityService:IEntityService
{
无效剂量测定(T项);
}
此模式在.Net类库中使用(例如,
IEnumerable
/
IEnumerable
IList
/
IList

如果您知道您的接口仅将泛型类型(
T
)用于输出,则可以使用
out
关键字
IMyInterface
。然后,您可以为
T
提供更派生的类型。这叫做协方差。然后,这些方法的返回值将产生使用者所期望的更派生的类型,这是正常的


如果它仅将泛型类型用于输入,请使用关键字
IMyInterface
中的
。然后可以为
T
提供派生程度较低的类型。这叫做逆变。然后,方法的输入参数将获得预期的更派生的类型,这是正常的。

如果
IEntityService,其中T:imongotentity
更改为
IEntityService,其中T:imongotentity
,我认为它会工作。你正在接近协方差isues@ScottChamberlain但是,泛型中的out关键字不是返回类型吗?所有方法都返回Task或TaskImagine
IEntityService
有一个
Add(T项)
方法。(我们不知道它是否有,但编译器不在乎。它可以。)现在想想这对
IEntityService
意味着什么——你可以向它添加任何mongo实体。现在,您可以将
管理项目
添加到
销售服务
?不。。。这就是它无效的原因。@JonSkeet啊,它太简单了!这是有道理的。
out
告诉编译器您没有任何
Add(T项)
调用。
IEntityService<IMongoEntity> service = fromsales ? 
    (IEntityService<IMongoEntity>)salesService : 
    (IEntityService<IMongoEntity>)mgmtService;
public interface IEntityService
{
    void DoSomething(object item);
}

public interface IEntityService<T> : IEntityService
{
    void DoSomething(T item);
}