8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

在类型参数化方法中无法将子类隐式转换为父类

bfh47 1月前

65 0

我最近必须帮助解决某人从通用方法返回时遇到的问题,尽管有多个问题需要解决,但我理解并能解释所有问题 - 除了......

我最近不得不帮助某人解决从通用方法返回时遇到的问题,虽然有多个问题需要解决,但我理解并能解释所有问题 - 除了让编译器接受返回类型的最后一个障碍。虽然我最终成功让程序编译并正确运行,但我仍然无法完全理解 为什么 必须这样做的逻辑。

我在下面用一个最小的例子重现了这个问题。给定一个非常简单的父子类结构,只有一个泛型方法:

abstract class AbstractParentClass
{
    public abstract T DoThing<T>() where T : AbstractParentClass;
}

class ConcreteChildClass : AbstractParentClass
{
    public override T DoThing<T>()
    {
        return this;
    }
}

这会导致返回行出现错误 Cannot implicitly convert type 'ConcreteChildClass' to 'T' 。有点奇怪,因为 T 被限制为的实例 AbstractParentClass ,并且 this 显然是其中之一,但好吧,当然,所以我们会明确地这样做:

public override T DoThing<T>()
{
    return (T) this;
}

现在错误消息显示为 Cannot convert type 'ConcreteChildClass' to 'T' 。什么?如果 T 不受约束,那么当然,我知道我们无法保证这一点,但是对于像我们这样的继承,它肯定应该是一个简单的转换?

我们可以通过明确转换为父类来接近:

public override T DoThing<T>()
{
    return (AbstractParentClass) this;
}

现在错误显示为 Cannot implicitly convert type 'AbstractParentClass' to 'T'. An explicit conversion exists (are you missing a cast?) 。为什么我们不能隐式转换为约束的确切类型——什么可能的情况会导致约束类型的类不能转换为......它自己?但至少现在这是可以解决的,错误消息甚至直接告诉我们如何做到这一点:

public override T DoThing<T>()
{
    return (T)(AbstractParentClass) this;
}

现在一切都运行正常。如果我们愿意,我们甚至可以让它看起来更漂亮一点:

public override T DoThing<T>()
{
    return this as T;
}

纵观这一切,如果 T 不受约束,我当然明白为什么这些转换不可能像书面上写的那样实现。但事实确实如此,而且编译器不应该有任何问题。编译器是否出于某种原因,在允许隐式转换时不考虑类型约束?根据我的经验,C# 中所有这样的情况背后都有很好的理由,我只是一辈子也想不出这个。

如果有人知道为什么编译器会对这段(看似!)非常简单的代码产生麻烦,我将非常感谢您解释允许这些转换的问题。

帖子版权声明 1、本帖标题:在类型参数化方法中无法将子类隐式转换为父类
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由bfh47在本站《oop》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 好吧。我同意从父类中返回的方法和你的方法一样糟糕,甚至更糟糕。有趣的是,使用接口,即使在子类中有显式接口调用,你也会遇到完全相同的错误。

返回
作者最近主题: