9

我相信我希望类的某些方法和属性是不可覆盖的,并在所有派生类中使用基类的实现。如何做到这一点?密封关键字似乎不起作用,并说“方法不能被密封,因为它不是覆盖”。

4

5 回答 5

15

成员在 C# 中默认是密封的 - 除非它们被标记为虚拟,否则它们无论如何都不能在派生类中被覆盖。

诚然,它们可以在派生类中隐藏:

public new void SomeMethod()
{
}

...但这与覆盖不同。没有办法阻止这种情况,但是如果调用者使用基类的编译时类型,他们无论如何都不会意外地调用它。

如果您可以向我们提供更多详细信息,说明您正在尝试防止什么(来自调用者的 POV 和被调用的代码),我们可能会提供更多帮助

于 2011-07-05T16:27:27.930 回答
5

除非您将其标记为 ,否则尚未被覆盖的方法将无法被覆盖virtual。所以听起来你的情况不需要采取任何行动。

class A
{
    public void B() {} // can't override
    public virtual C() {} // can override
    public virtual D() {} // can override
}

sealed仅当方法已经是基类中成员的覆盖时,该修饰符才适用。这允许您防止在该类的子类中覆盖

class A1 : A
{
    public void B() {} // shadows A.B.  Not a virtual method!
    public override C() {} // overrides A.C, subclasses can override
    public override sealed D() {} // overrides A.D, subclasses cannot override
                                  // (but can shadow)
}
于 2011-07-05T16:28:54.527 回答
2

这是不可能的。派生类始终可以使用 new 关键字来隐藏(而不是覆盖)其父方法。sealed 关键字只是阻止派生类覆盖虚拟方法,但它仍然可以使用 new 隐藏基方法。

于 2011-07-05T16:27:44.963 回答
1

仅当您覆盖一个虚拟方法但不希望从您的实现派生的类再次覆盖它时,才能使用“sealed”关键字。您只需要声明该方法不是虚拟的。

正如其他人指出的那样,实际上有一个“new”关键字,它允许隐藏该方法。但只要你使用基类的引用,你的基方法就会被调用:

class BaseClass
{
     public void Foo() { Console.WriteLine("Foo"); }
}

class Derived : BaseClass
{
     public new void Foo() { Console.WriteLine("Bar"); }
}

public static void Main()
{
     Derived derived = new Derived();
     derived.Foo(); // Prints "Bar"
     BaseClass baseClass = derived;
     baseClass.Foo(); // Prints "Foo"
}

由于只提供基类才有意义,只要您在任何地方都使用“BaseClass”指针,您的方法就无法隐藏。

于 2011-07-05T16:32:03.610 回答
0

这正是sealed关键字的用途。

http://msdn.microsoft.com/en-us/library/ms173150.aspx

派生类上重写基类的虚拟成员的类成员、方法、字段、属性或事件可以将该成员声明为密封的。这否定了任何进一步派生类的成员的虚拟方面。这是通过在类成员声明中将sealed 关键字放在覆盖关键字之前来实现的。

如果您从基类重写了一个方法而不是使用sealed. 如果您在类中声明了一个方法并且不希望它在任何派生类中被覆盖,那么不要将其标记为virtual. 只有virtual成员可以被覆盖。

于 2011-07-05T16:27:52.873 回答