这个:
public sealed class MyClass
{
protected void MyMethod(){}
}
编译通过,但是会有警告
而这段代码:
public sealed class MyClass
{
public virtual void MyMethod(){}
}
无法编译。只是出于好奇,这有什么原因吗?
public sealed class MyClass
{
protected void MyMethod(){}
}
编译通过,但是会有警告
而这段代码:
public sealed class MyClass
{
public virtual void MyMethod(){}
}
无法编译。只是出于好奇,这有什么原因吗?
sealed
与virtual
或protected
不太相符合。他想知道为什么一个“不合理”的项目被允许,而另一个则不行。 - Sam Harwellprotected override void Foo()
但不包括这个
protected void Foo()
但这可能会被认为有点难以理解 - 就是override
的缺失使其无用,而在另一种情况下
public virtual void Foo()
虚拟的存在是没有用的,而“错误”的存在可能比有用的东西的缺失更容易理解。
在这种情况下,虚拟可能会对性能产生影响,而将某些内容保护起来而不是私有的可能不会产生影响 - 所以它更严重一些。
这只是猜测 - 如果我们真的很幸运,Eric Lippert会给出一个更明确的答案。他才是你想要的人,而不是我 :)
最佳答案:将警告视为错误,它们就是等价的;)
我看不出来这样做有什么好处。受保护的MyMethod可以从MyClass中调用,但永远不会从派生类中调用(因为MyClass是密封的)。虚拟版本也允许直接从MyClass中调用,但方法不能有重写,因为你不能从MyClass派生一个类...
封闭类可以通过继承拥有受保护的成员。
当一个方法是一个类的一部分时,无论这个方法是如何得到的都没有关系。
在第一种情况下,对于封闭类上的受保护方法,它与封闭类继承受保护方法是相同的。因此,它可以编译。
出于好奇,到底给出了什么警告?
首先,虽然在封闭类中包含新的CS0549:'function'是封闭类'class'中的一个新虚成员。
protected
或virtual
成员并不合理,但CLI¹确实允许这样做。CLI还允许使用callvirt
IL指令调用封闭类的成员,尽管编译器可以自由地将其替换为call
指令。作为密封的当应用于类时,sealed修饰符会阻止其他类从它继承。
在这里我正在逐一解释:
public sealed class MyClass
{
protected void MyMethod(){}
}
它会给你警告,因为实际上这是没有意义的。因为在将类声明为sealed之后,您无法继承它,而且由于您的方法是protected
,所以您无法使用其对象在类外部访问它(还要记住,您也无法创建此类的子类,因此您也无法通过该技巧使用此方法)。因此,在实践中,将其设置为protected
是没有意义的,因此编译器会给出警告。但是,如果将其设置为public
或internal
,则不会出现错误,因为在这种情况下它是有用的。
现在是第二个问题:
public sealed class MyClass
{
public virtual void MyMethod(){}
}
你已经将类封装起来,现在你正在将方法设置为虚拟的,这样间接地给了别人覆盖它的机会,而这只能通过继承实现。这里出现了问题,因为你的类是被封装的,所以无法对该类执行继承操作。这就是为什么使用 virtual
会出错。
希望这可以帮助你理解。