泛型和转换 - 不能将继承的类转换为基类 [英] Generics and casting - cannot cast inherited class to base class

查看:26
本文介绍了泛型和转换 - 不能将继承的类转换为基类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这是旧的,但我仍然不太擅长理解这些问题.谁能告诉我为什么以下不起作用(抛出一个 runtime 关于强制转换的异常)?

I know this is old, yet I am still not very good with understanding those problems. Can anyone tell me why the following does not work (throws a runtime exception about casting)?

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;

那么,谁能解释一下这是怎么无效的?而且,我你没有心情解释 - 有没有一行代码我可以用来实际执行这个转换?

So, can anyone explain how is this invalid? And, I you are not in the mood to explain - is there a line of code I can use to actually do this cast?

推荐答案

RepositoryBase 不是 MyEntityRepository 的基类.您正在寻找通用方差,它在 C# 中存在的范围有限,但在此处不适用.

RepositoryBase<EntityBase> is not a base class of MyEntityRepository. You're looking for generic variance which exists in C# to a limited extent, but wouldn't apply here.

假设你的 RepositoryBase 类有一个这样的方法:

Suppose your RepositoryBase<T> class had a method like this:

void Add(T entity) { ... }

现在考虑:

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

现在您已经向 MyEntityRepository 添加了一种不同类型的实体......这不可能是正确的.

Now you've added a different kind of entity to a MyEntityRepository... and that can't be right.

基本上,泛型方差仅在某些情况下是安全的.特别是泛型 covariance(这就是你在这里描述的)只有在你只从 API 中取出"值时才是安全的;通用逆变(反过来工作)只有在您只将值放入"API 时才是安全的(例如,可以按面积比较任何两个形状的一般比较可以被视为比较方格).

Basically, generic variance is only safe in certain situations. In particular generic covariance (which is what you're describing here) is only safe when you only ever get values "out" of the API; generic contravariance (which works the other way round) is only safe when you only ever put values "into" the API (e.g. a general comparison which can compare any two shapes by area can be considered as a comparison of squares).

在 C# 4 中,这可用于泛型接口和泛型委托,而不是类 - 并且仅适用于引用类型.请参阅 MSDN 了解更多信息,阅读 阅读 C# in Depth,第二版,第 13 章或 Eric Lippert 关于该主题的博客系列.此外,我于 2010 年 7 月在 NDC 上发表了一个小时的演讲 - 该视频可在此处获得.

In C# 4 this is available for generic interfaces and generic delegates, not classes - and only with reference types. See MSDN for further information, read <plug>read C# in Depth, 2nd edition, chapter 13</plug> or Eric Lippert's blog series on the topic. Also, I gave a one hour talk about this at NDC in July 2010 - the video is available here.

这篇关于泛型和转换 - 不能将继承的类转换为基类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆