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

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

Linces games 1月前

62 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 除非注明,本帖由Linces games在本站《oop》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我给出的示例的主要优势在于,如果扩展基类的人可能比调用方法的人更紧密地遵守(并认真对待)要遵循的规则。例如,如果您正在编写一个库,您将在其中提供扩展父类的各种类的实现,并且您期望库的使用者在这些实例上调用 DoThing,那么编译器不会阻止您搞砸,但至少它可以阻止库的使用者在其方法调用中提供错误的泛型类型。

返回
作者最近主题: