将受约束的泛型参数从子类型转换为超类型

本文关键字:类型转换 超类 类型 受约束 泛型 参数 | 更新日期: 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) {
    ....
}

可能同样适合该任务,因为它没有欺骗编译器的转换,并且调用代码的结构将保持不变。