小编典典

泛型和强制转换-无法将继承的类强制转换为基类

c#

我知道这很老了,但我对理解这些问题仍然不太满意。谁能告诉我以下内容为何不起作用(引发runtime铸造异常)?

public abstract class EntityBase { }
public class MyEntity : EntityBase { }

public abstract class RepositoryBase<T> where T : EntityBase { }
public class MyEntityRepository : RepositoryBase<MyEntity> { }

现在,铸造线:

MyEntityRepository myEntityRepo = GetMyEntityRepo(); // whatever
RepositoryBase<EntityBase> baseRepo = (RepositoryBase<EntityBase>)myEntityRepo;

那么,谁能解释这是无效的吗?而且,我不打算解释-是否可以使用一行代码来实际执行此转换?


阅读 277

收藏
2020-05-19

共1个答案

小编典典

RepositoryBase<EntityBase>不是 一个基类MyEntityRepository。您正在寻找在C#中有限存在的
通用方差 ,但不适用于此处。

假设您的RepositoryBase<T>类具有如下方法:

void Add(T entity) { ... }

现在考虑:

MyEntityRepository myEntityRepo = GetMyEntityRepo(); // whatever
RepositoryBase<EntityBase> baseRepo = (RepositoryBase<EntityBase>)myEntityRepo; 
baseRepo.Add(new OtherEntity(...));

现在,您已经向…添加了另一种类型的实体MyEntityRepository,那是不对的。

基本上,一般差异仅在某些情况下才是安全的。特别是泛型 协方差 (这就是您在此处描述的)仅在您仅从API之外获取值时才是安全的。仅当您只将值“放入”
API时,通用 逆差反之亦然 )才是安全的(例如,可以按面积比较任意两个形状的常规比较可以视为平方比较)。

在C#4中,它适用于通用接口和通用委托,不适用于类-
仅适用于引用类型。有关更多信息,请参见MSDN,请阅读Deplugth,第二版,第13章,
read C# 或Eric Lippert
关于该主题的博客系列。另外,我在2010年7月的NDC上做了一个小时的演讲-
视频可在此处获得

2020-05-19