我知道这很老了,但我对理解这些问题仍然不太满意。谁能告诉我以下内容为何不起作用(引发runtime铸造异常)?
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;
那么,谁能解释这是无效的吗?而且,我不打算解释-是否可以使用一行代码来实际执行此转换?
RepositoryBase<EntityBase>是 不是 一个基类MyEntityRepository。您正在寻找在C#中有限存在的 通用方差 ,但不适用于此处。
RepositoryBase<EntityBase>
MyEntityRepository
假设您的RepositoryBase<T>类具有如下方法:
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# plug>或Eric Lippert 关于该主题的博客系列。另外,我在2010年7月的NDC上做了一个小时的演讲- 视频可在此处获得。