将受约束的泛型参数从子类型转换为超类型
本文关键字:类型转换 超类 类型 受约束 泛型 参数 | 更新日期: 2023-09-27 17:56:07
我有一个这样的泛型函数:
private LOCAL_TYPE RemoteToLocal<LOCAL_TYPE>(RemoteObjectBaseType remoteObject)
where LOCAL_TYPE: EntityBase
{
Type t = typeof(LOCAL_TYPE);
if (t == typeof(FavoritePlace))
{
return new FavoritePlace(remoteObject as RemotePlaceType1);
}
}
其中EntityBase
是非抽象类。 FavoritePlace
类继承自EntityBase
.
但是,我收到一个错误:
不能将类型Common.Model.FavoritePlace隐式转换为"LOCAL_TYPE"。
这让我想知道:FavoritePlace 是 EntityBase 的子项,LOCAL_TYPE被限制为实体库类型。为什么转换不能发生?我可能在这里错过了一些重要的东西。
编辑:好的,根据当前的答案和一些实验,我找到了另一种解决方法,即进行以下转换:
if (t == typeof(FavoritePlace))
{
return (LOCAL_TYPE)(EntityBase)new FavoritePlace(remoteObject);
}
现在编译器很高兴。但我只是想知道,如果从编译器的角度来看这种转换是可能的,为什么直接转换为LOCAL_TYPE不是?转换为关系不是可传递的吗?
问题是FavoritePlace
不一定是LOCAL_TYPE
的类型。如果你有
class OtherEntity : EntityBase { }
然后您在通话时无法返回FavoritePlace
var entity = RemoteToLocal<OtherEntity>(remoteObject);
如果您知道转换是安全的,您可以使用演员表来解决它:
return (LOCAL_TYPE)(object)new FavoritePlace(remoteObject as RemotePlaceType1);
虽然你已经通过运行时代码确定LOCAL_TYPE
实际上是FavoritePlace
的,但编译器在静态上没有相同的知识。编译器希望你返回一个类型为 LOCAL_TYPE
的对象,与方法的类型参数完全匹配。
想到这种情况:有人打了如下电话——
var res = RemoteToLocal<MostHatedPlace>(remoteObj); // MostHatedPlace derives from EntityBase
现在你在里面 RemoteToLocal
,你经历了一些条件,现在是时候返回结果了。你打电话
return new FavoritePlace(remoteObject as RemotePlaceType1);
您知道代码中的此分支是不可能到达的,因为有一个运行时检查可以保护您:
if (t == typeof(FavoritePlace)) {
....
}
但是,编译器必须假设可以到达此返回语句,这在LOCAL_TYPE
不是FavoritePlace
的情况下将是一个错误。
您可能需要在此处重新考虑泛型的使用:从代码片段来看,您似乎需要泛型参数来避免将结果类型转换为调用者中的所需类型。但是,调用方随后需要执行其他检查,以查看RemoteToLocal
内的转换是否成功。在这种情况下,一个方法
private EntityBase RemoteToLocal(RemoteObjectBaseType remoteObject) {
....
}
可能同样适合该任务,因为它没有欺骗编译器的转换,并且调用代码的结构将保持不变。