C#中的密封方法

时间:2010-11-11 06:58:04

标签: c# sealed

我是C#的新手。我正在读关于密封的关键字。我有关于密封的类。我读了一条关于密封方法的线,我们也可以制作密封方法。线是(通过声明方法如果密封,我们可以避免进一步覆盖这种方法。) 我已经创建了一个demo但是没有理解上面的行和密封方法的含义使用。以下是我的代码: -

using System;

namespace ConsoleApplication2
{
    class Program:MyClass
    {
        public override sealed void Test()
        {
            Console.WriteLine("My class Program");
        }
        static void Main(string[] args)
        {
            Program obj = new Program();
            obj.Test();
            Console.ReadLine();
        }
    }

    class MyClass
    {
        public virtual void Test()
        {
            Console.WriteLine("My class Test");
        }
    }


}

请告诉我为什么我们使用密封方法以及密封方法的优点。

7 个答案:

答案 0 :(得分:69)

密封的是一个类,它不能是另一个派生类的基类。

未密封类中的密封方法是一种无法在此类的派生类中重写的方法。

  

为什么我们使用密封方法?密封方法有哪些优点?

那么,为什么要使用虚拟方法? 提供可以自定义类行为的点。那你为什么要使用密封方法呢? 提供一个点,在该点保证,对于此方法,任何派生类的行为都不会发生进一步的更改。

可以自定义类行为的点有用危险。它们很有用,因为它们使派生类能够改变基类的行为。它们很危险......等待它...... 因为它们使派生类能够改变基类的行为。虚拟方法基本上允许第三方使您的类做疯狂您从未预料到或测试过的事情。

我喜欢编写符合我预期和测试内容的代码。密封方法允许您继续允许类的部分被覆盖,同时使密封方法具有无法进一步定制的保证,可测试,稳定的行为。

答案 1 :(得分:68)

嗯,你只测试了两个级别的继承,而你没有达到你“进一步覆盖”一个方法的程度。如果你把它变为三,你可以看到sealed做了什么:

class Base {
   public virtual void Test() { ... }
}
class Subclass1 : Base {
   public sealed override void Test() { ... }
}
class Subclass2 : Subclass1 {
   public override void Test() { ... } // Does not compile!
   // If `Subclass1.Test` was not sealed, it would've compiled correctly.
}

答案 2 :(得分:20)

好吧,如果您不希望任何派生类进一步覆盖您的方法,那么您只能在方法上使用“sealed”。默认情况下,方法是密封的,如果它们未被声明为虚拟方法而不是覆盖另一个虚方法。 (在Java中,默认情况下方法是虚拟的 - 要实现“默认”C#行为,您必须将方法标记为final。)

我个人喜欢仔细控制继承 - 我更喜欢在可能的情况下密封整个类。但是,在某些情况下,您仍希望允许继承,但请确保不会进一步覆盖某些方法。一种用途可能是有效template the method,例如用于诊断:

public sealed override void Foo(int x)
{
    Log("Foo called with argument: {0}", x);
    FooImpl(x);
    Log("Foo completed");
}

protected abstract void FooImpl(int x);

现在,子类不能直接覆盖Foo - 它们必须覆盖FooImpl,因此当其他代码调用{{1}时,我们的行为将始终执行}。

当然,模板可能出于其他原因 - 例如强制执行参数验证的某些方面。

根据我的经验,密封方法并不经常使用,但我很高兴有能力。 (我只是希望课程默认密封,但那是另一个对话。)

答案 3 :(得分:1)

现在,如果您声明Program的子类,您将无法覆盖Test方法,这就是重点。

在大多数情况下,您不需要密封方法,但是当您为某些插件系统开发基类时,它们可以证明自己很有用,第三方开发人员必须扩展这些基类才能创建自己的插件。您可以保留一些服务数据,如插件名称以及是否已启用,并使用密封方法和属性来执行此操作,因此插件开发人员不会弄乱它。这是密封成员派上用场的一个案例

答案 4 :(得分:1)

密封方法

密封方法用于定义虚拟方法的覆盖级别。

密封关键字始终与覆盖关键字一起使用。

密封方法的实际演示

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace sealed_method
{
    class Program
    {
        public class BaseClass
        {

            public virtual void Display()
            {
                Console.WriteLine("Virtual method");
            }
        }

       public class DerivedClass : BaseClass
        {
            // Now the display method have been sealed and can;t be overridden
            public override sealed void Display()
            {
                Console.WriteLine("Sealed method");
            }
        }

       //public class ThirdClass : DerivedClass
       //{

       //    public override void Display()
       //    {
       //        Console.WriteLine("Here we try again to override display method which is not possible and will give error");
       //    }
       //}

        static void Main(string[] args)
        {

            DerivedClass ob1 = new DerivedClass();
            ob1.Display();

            Console.ReadLine();
        }
    }
}

答案 5 :(得分:0)

首先,让我们从定义开始。密封是一个修饰符,如果将其应用于类将使其不可继承,并且如果将其应用于虚拟方法或属性则将使其不可验证

public sealed class A { ... }
public class B 
{
    ...
    public sealed string Property { get; set; }
    public sealed void Method() { ... }
}

其用法的一个例子是专门的类/方法或属性,其中潜在的更改可能会使它们停止按预期方式工作(例如,System.Drawing命名空间的Pens类)。

...
namespace System.Drawing
{
    //
    // Summary:
    //     Pens for all the standard colors. This class cannot be inherited.
    public sealed class Pens
    {
        public static Pen Transparent { get; }
        public static Pen Orchid { get; }
        public static Pen OrangeRed { get; }
        ...
    }
}

因为不能继承密封类,所以不能将其用作基类,因此,抽象类不能使用密封修饰符。同样重要的是要提到结构是隐式密封的

示例

public class BaseClass {
    public virtual string ShowMessage()
    {
        return "Hello world";
    }
    public virtual int MathematicalOperation(int x, int y)
    {
        return x + y;
    }
}
public class DerivedClass : BaseClass {
    public override int MathematicalOperation(int x, int y) 
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior
        return x - y;
    }
    public override sealed string ShowMessage()
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior but because it's sealed prevent classes that derive from it to override the method
        return "Hello world sealed";
    }
}
public class DerivedDerivedClass : DerivedClass
{
    public override int MathematicalOperation(int x, int y)
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior
        return x * y;
    }
    public override  string ShowMessage() { ... } // compile error
}
public sealed class SealedClass: BaseClass {
    public override int MathematicalOperation(int x, int y)
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior
        return x * y;
    }
    public override string ShowMessage()
    {
        // since BaseClass has a method marked as virtual, DerivedClass can override it's behavior but because it's sealed prevent classes that derive from it to override the method
        return "Hello world";
    }
}
public class DerivedSealedClass : SealedClass
{
    // compile error
}

Microsoft文档

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/sealed

答案 6 :(得分:-5)

C#拥有它,因为Java具有相同的功能(final方法)。我从未见过合法用途。

如果您不想允许扩展,则应将整个班级标记为sealed,而不仅仅是一种方法。