C# 当当前类是子类时,为什么在方法或属性上使用sealed

C# 当当前类是子类时,为什么在方法或属性上使用sealed,c#,C#,当当前类从超类继承时,为什么要在方法或属性上使用sealed关键字?假设我们创建了一个类,并且倾向于向对象用户公开它的一个或多个方法,但不让它被继承,并使用sealed来解决这个问题。那么,为什么不呢?仅仅密封当前继承类的方法或属性的原因是什么?如文档()中所述,这会阻止方法成为虚拟的。它很有用,因为override关键字意味着虚拟。如果要重写方法但停止进一步重写,可以将sealed添加到方法定义中 如果类本身是密封的,则没有理由密封特定的方法,因为该类无论如何都无法继承。您将密封的应用于重写的

当当前类从超类继承时,为什么要在方法或属性上使用
sealed
关键字?假设我们创建了一个类,并且倾向于向对象用户公开它的一个或多个方法,但不让它被继承,并使用
sealed
来解决这个问题。那么,为什么不呢?仅仅密封当前继承类的方法或属性的原因是什么?

如文档()中所述,这会阻止方法成为虚拟的。它很有用,因为override关键字意味着虚拟。如果要重写方法但停止进一步重写,可以将sealed添加到方法定义中


如果类本身是密封的,则没有理由密封特定的方法,因为该类无论如何都无法继承。

您将
密封的
应用于重写的方法(或属性等),以禁止从类派生的类,进一步重写该方法。

密封类或方法有两个主要原因

第一个,也是最重要的一个(可能)是您不允许对所讨论的类型或方法进行继承。在某些情况下,这可能很重要

第二个原因是编译器可以应用优化,否则就无法完成

执行虚拟方法查找不是一件非常昂贵的事情,但它确实会产生一些开销。如果编译器知道:

  • 在给定的情况下,您使用的是最具体的类
  • 给定的类型或方法是密封的

  • 然后在某些情况下,它可以将对方法的调用编译为对正确方法的直接调用,而不是通过该类型的虚拟方法表进行查找。这将消除这种情况下虚拟方法查找的开销。

    如MSDN文档中所述:

    您还可以对以下方法或属性使用密封修饰符: 重写基类中的虚拟方法或属性。这使得 您必须允许类从类派生,并防止它们 重写特定的虚拟方法或属性

    换句话说,您可以阻止重写在类继承层次结构的更底层发生。作为一个程序员,您基本上是说这个特定的方法应该具有所有子类的通用功能

    下面是同一篇文章中的一个很好的代码示例:

    class X
    {
        protected virtual void F() { Console.WriteLine("X.F"); }
        protected virtual void F2() { Console.WriteLine("X.F2"); }
    }
    
    class Y : X
    {
        sealed protected override void F() { Console.WriteLine("Y.F"); }
        protected override void F2() { Console.WriteLine("Y.F2"); }
    }
    
    class Z : Y
    {
        // Attempting to override F causes compiler error CS0239. 
        // protected override void F() { Console.WriteLine("C.F"); }
    
        // Overriding F2 is allowed. 
        protected override void F2() { Console.WriteLine("Z.F2"); }
    }
    
    根据额外澄清请求进行更新

    下面是一个不太抽象的示例,展示了一个
    密封的
    方法的可能应用程序

    abstract class Car
    {
        public abstract void Make();
    }
    
    class Ford : Car
    {
        // We don't want someone inheriting from this class to change the
        // 'Make' functionality - so we seal the method from being further
        // overridden down the inheritance hierarchy 
        sealed public override void Make() { Console.WriteLine("Ford"); }
    }
    
    // This way there is no way (besides shadowing) someone inheriting from Ford
    // can change the behavior of Make() - so these two types will contain the 
    // same behavior. Pretty nice, eh!? 
    class Focus : Ford
    { 
    }
    
    class Escape : Ford
    {
    }
    

    这就是我模棱两可的地方;为什么我们要停止这个继承链接呢?没错,我们写下一个类作为基础类,然后逐级继承,但突然我们在非密封类中的方法或属性上使用了
    sealed
    ,但也从该类继续继承过程。我们为什么要这么做?我更新了一个不那么抽象的例子。现在很清楚,这允许在所有子类型中表达公共功能吗?现在我明白了。非常感谢德里克,你是最棒的:)