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

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

问题描述

我知道这是老,但我仍然不是很好理解这些问题。任何人都可以告诉我为什么以下不工作(抛出运行时关于铸造的异常)?

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

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

现在投放线:

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

那么,任何人都可以解释这是无效的吗?

解决方案

p> RepositoryBase< EntityBase> 不是 MyEntityRepository 的基类。您正在寻找有限范围内存在于C#中的泛型方差,但不适用于此处。



假设您的 RepositoryBase< T> 类有这样的方法:

  ){...} 

现在考虑:

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

现在,您已向 MyEntityRepository ...而且不能是正确的。



基本上,一般方差只在某些情况下是安全的。特别是泛型协方差(这是你在这里描述的)只有当你只得到值out的API;泛型(反向工作)只有在你只将值放入API时才是安全的(例如,一个可以比较任何两个形状的一般比较可以被视为一个比较。在C#4中,这可用于通用接口和通用委托,而不是类,只能使用引用类型。有关详细信息,请参见 MSDN ,阅读< plug> read C#in Depth,第2版,第13章< / plug>或Eric Lippert的博客系列。此外,我在2010年7月在NDC上进行了一个小时的讨论 - 该视频可供此处使用;只需搜索方差。


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> { }

And now the casting line:

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<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.

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

void Add(T entity) { ... }

Now consider:

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

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

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).

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; just search for "variance".

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

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