理解非法泛型强制转换
本文关键字:转换 泛型 非法 | 更新日期: 2023-09-27 18:14:44
我很难理解为什么我执行的强制转换会抛出运行时异常,说明它是非法的强制转换。我做了一些研究,找到了这个答案,这让我看到了MSDN文章泛型中的协方差和逆变变。但是,我仍然有点困惑,所以如果有人能帮助澄清,我将不胜感激。
下面是两个类类型的对象层次结构:
IMongoEntity (interface)
| - MongoEntity (abstract)
| | -SalesProject (concrete)
| | -ManagementProject (concrete)
IEntityService<T> where T : IMongoEntity (interface)
| -EntityService<T> where T : IMongoEntity (concrete superclass)
| | - MgmtService : EntityService<ManagementProject> (subclass)
| | - SalesService : EntityService<SalesProject> (subclass)
创建这两个非通用服务只是为了让我可以创建一些特定的方法,这些方法只适用于这些特定的类型(本质上是预定义的数据库查找)。
然后有这一行,它抛出InvalidCastException
:
IEntityService<IMongoEntity> service = fromsales ?
(IEntityService<IMongoEntity>)salesService :
(IEntityService<IMongoEntity>)mgmtService;
由于两个服务都是从相同的接口派生的&抽象类和使用的类型参数是从同一个抽象类派生的,那么为什么这种强制转换是非法的?
注意:我有变通方法,所以我不是真的在寻找解决方案,而是我想了解为什么这是不允许的。
MyType<Base>
和MyType<Derived>
没有任何继承关系,即使Derived
是由Base
派生的。这两种泛型只是两种不同的类型。
public interface IEntityService
{
void DoSomething(object item);
}
public interface IEntityService<T> : IEntityService
{
void DoSomething(T item);
}
此模式在。net类库中使用(例如IEnumerable
/IEnumerable<T>
, IList
/IList<T>
)。
如果您知道您的接口只对输出使用泛型类型(T
),则可以使用out
关键字IMyInterface<out T>
。然后可以为T
提供更派生的类型。这叫做协方差。然后,方法的返回值将产生消费者所期望的更派生的类型,这是可以的。
如果它只对输入使用泛型类型,则使用in
关键字IMyInterface<in T>
。然后可以为T
提供派生程度较低的类型。这叫做逆变。然后,方法的输入参数将获得预期的更派生的类型,这是可以的。