gpt4 book ai didi

c# - 为什么静态在编译时隐藏重写的方法?

转载 作者:太空狗 更新时间:2023-10-30 00:15:25 25 4
gpt4 key购买 nike

给定:

class BaseClass
{
public virtual void M(int x)
{

}
}

class Derived : BaseClass
{
public override void M(int x)
{
base.M(x);
}

static void M(object x)
{

}

static void Main()
{
var d = new Derived();
d.M(0);
}
}

错误:

Member 'Derived.M(object)' cannot be accessed with an instance reference; qualify it with a type name instead

查看 C# 4.0 规范第 7.4 节(成员查找),第一个要点如下:

A member lookup of a name N with K type parameters in a type T is processed as follows:

[...] Members that include an override modifier are excluded from the set [of accessible members named N]

由此我得出结论,覆盖 Derived.M 不再可访问。相反,编译器必须引用 BaseClass.M

但是,这并不能解释为什么添加静态的Derived.M 会突然导致编译错误。编译器现在只能看到静态成员 Derived.M 并断定该成员是无效调用。如果我删除静态 Derived.M 则编译成功。

为什么会这样?

最佳答案

似乎发生了以下步骤,它们共同导致了编译器错误:

  • 第 1 步:因为 7.4 中的部分。你引用,M 的实例版本被删除,只留下静态版本的编译器。 static的参数类型是object,兼容int。方法名称也匹配。
  • 第2步:成员查找完成,因为已经找到了匹配的方法(正确的名称,兼容的参数),不需要向上继承链。
  • 第 3 步:现在才检查该方法是实例方法还是静态方法。

我真的不能引用规范中的一句话来证明这一点,但是 §7.4(成员查找)和 §3.5(可访问性)都没有谈论 static 与实例,所以我假设这个在进行成员查找时,根本根本不考虑事实。

§7.4 中的相关部分似乎是:

A member lookup of a name N with K type parameters in a type T is processed as follows:

  • First, a set of accessible members named N is determined:
    [...]
    The set consists of all accessible (§3.5) members named N in T, including inherited members and the accessible members named N in object. If T is a constructed type, the set of members is obtained by substituting type arguments as described in §10.3.2. Members that include an override modifier are excluded from the set.

我理解这部分的方式就像上面解释的那样:它会返回实例方法和静态方法,然后删除实例方法,因为它有 override 修饰符。
此时只剩下静态方法了。

结尾是这样的:

Finally, [...], the result of the lookup is determined:
if the set contains only methods, then this group of methods is the result of the lookup.

因此,结果是静态方法。

显然,此问题只发生在您具有类层次结构并且派生类之一声明具有相同名称和兼容参数的静态方法的情况下。

将这样一个静态方法添加到现有类中的情况是,简单地向类中添加一些内容仍然是破坏性更改

虽然我很确定你知道如何解决编译器错误,但我仍然会陈述它,以获得完整的答案:
使用任何基类作为变量的编译时类型。运行时类型仍然可以是派生类型,这不是问题:

BaseClass d          = new Derived();
// ^ ^
// compile time type runtime type

关于c# - 为什么静态在编译时隐藏重写的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15006746/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com