为什么这个C#类声明编译?

BFr*_*ree 8 .net c# sealed

这个问题确实有点无意义,但我只是好奇:

这个:

public sealed class MyClass
{
   protected void MyMethod(){}
}
Run Code Online (Sandbox Code Playgroud)

编译,但发出警告

而这个:

public sealed class MyClass
{
   public virtual void MyMethod(){}
}
Run Code Online (Sandbox Code Playgroud)

不编译.出于纯粹的好奇心,这是有原因的吗?

Kev*_*ose 12

virtual用于声明方法/属性"override-able".

sealed用于声明该类不能继承.

因此,密封类中的虚方法永远不会被覆盖,因为该类永远不会被继承.它没有意义.

protected会影响对成员的访问,它不会像虚拟那样声明它"可覆盖"(尽管它经常以这种方式使用),因此并不矛盾.


Jon*_*eet 4

我能想到的唯一原因是有时您需要编写受保护的方法来覆盖其他受保护的方法。该语言本来可以被设计成允许这样做:

protected override void Foo()
Run Code Online (Sandbox Code Playgroud)

但不是这个

protected void Foo()
Run Code Online (Sandbox Code Playgroud)

但这可能被认为有点难以理解——缺乏它使得override毫无用处,而在

public virtual void Foo()
Run Code Online (Sandbox Code Playgroud)

它的存在virtual是无用的。“错误”的东西的存在可能比有用的东西的缺失更容易理解。

在这种情况下,虚拟化也可能会对性能产生影响,而将某些东西设置为受保护而不是私有可能不会 - 所以它更严重一些。

这些实际上只是猜测——如果我们真的很幸运,埃里克·利珀特(Eric Lippert)会给出更明确的答案。他是你想要的那个人,不是我:)

最佳答案:将警告视为错误,无论如何它们都是等效的;)

  • 嘿,我也只是猜测,伙计们。语言设计注释记录了 1999 年 10 月 18 日做出的将虚拟方法引入密封类型的决定是错误的,但没有给出该决定的任何理由。我在注释中找不到任何地方可以证明为什么引入新的受保护成员应该是合法的。我最好的猜测:这可能只是第一个版本中的一个疏忽,然后它成为修复它的重大更改。 (2认同)
  • @Eric:出于兴趣,这在规范中的哪里?它似乎不在 10.6 的介绍部分中,该部分列出了修饰符的有效组合的规则。我以为我会找到规则,然后看看它是否在任何带注释的规范中提到......但现在我找不到规则。我在10.6.3中也看不到它。 (2认同)