简体   繁体   English

C#中的密封方法

[英]Sealed method in C#

I am a newbie in C#.I am reading about Sealed keyword.I have got about sealed class.I have read a line about Sealed method where we can make Sealed method also.The line was ( By declaring method as sealed, we can avoid further overriding of this method. ) I have created a demo but didn't understand that the meaning of above line and sealed method use.我是 C# 新手。我正在阅读有关 Sealed 关键字的信息。我了解了 Sealed 类。我已经阅读了有关 Sealed 方法的一行,我们也可以在其中创建 Sealed 方法。该行是(通过将方法声明为已密封,我们可以避免进一步覆盖此方法。 )我创建了一个演示,但不明白上述行和密封方法的含义。 Below is my code:-以下是我的代码:-

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");
        }
    }


}

Please tell me why we use Sealed methods and what are the advantages of Sealed methods.请告诉我为什么我们使用 Sealed 方法以及 Sealed 方法的优点是什么。

Well, you are testing with only two levels of inheritance, and you are not getting to the point that you're "further overriding" a method.好吧,您仅使用两个继承级别进行测试,并且您还没有达到“进一步覆盖”方法的地步。 If you make it three, you can see what sealed does:如果你把它变成三个,你可以看到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.
}

A sealed class is a class which cannot be a base class of another more derived class.密封是不能成为另一个派生类的基类的类。

A sealed method in an unsealed class is a method which cannot be overridden in a derived class of this class.在未密封类的密封方法是不能在派生类这个类的被覆盖的方法。

Why do we use sealed methods?为什么我们使用密封方法? What are the advantages of sealed methods?密封方法有哪些优点?

Well, why do you use virtual methods?那么,为什么要使用虚方法呢? To provide a point at which behaviour of a class can be customized .提供一个可以自定义类行为的点 So why do you use sealed methods?那么为什么要使用密封方法呢? To provide a point at which you are guaranteed that no further changes will occur in the behaviour of any derived class with respect to this method .提供一个点,保证您不会在任何派生类的行为中发生关于此方法的进一步更改

Points where the behaviour of a class can be customized are useful but dangerous .可以自定义类的行为的点很有用但很危险 They are useful because they enable derived classes to change behaviour of the base class.它们很有用,因为它们使派生类能够改变基类的行为。 They are dangerous... wait for it... because they enable derived classes to change behaviour of the base class .它们很危险……等等……因为它们使派生类能够改变基类的行为 Virtual methods basically allow third parties to make your classes do crazy things that you never anticipated or tested.虚拟方法基本上允许第三方让你的类做你从未预料到或测试过的疯狂事情。

I like writing code that does what I anticipate and what I tested.我喜欢编写能够满足我的预期和测试的代码。 Sealing a method allows you to continue to allow parts of the class to be overridden while making the sealed methods have guaranteed, testable, stable behaviour that cannot be further customized.密封方法允许您继续允许类的某些部分被覆盖,同时使密封方法具有无法进一步定制的有保证的、可测试的、稳定的行为。

Well, you'd only use "sealed" on a method if you didn't want any derived classes to further override your method.好吧,如果您不希望任何派生类进一步覆盖您的方法,则只能在方法上使用“密封”。 Methods are sealed by default, if they're not declared as virtual and not overriding another virtual method.如果方法未声明为虚拟方法且未覆盖另一个虚拟方法,则默认情况下它们是密封的。 (In Java, methods are virtual by default - to achieve "default" C# behaviour you have to mark a method as final .) (在 Java 中,默认情况下方法是虚拟的 - 要实现“默认”C# 行为,您必须将方法标记为final 。)

Personally I like to control inheritance carefully - I prefer whole classes to be sealed where possible.我个人喜欢小心地控制继承——我更喜欢尽可能密封整个类。 However, in some cases you still want to allow inheritance, but ensure that some methods aren't overridden further.但是,在某些情况下,您仍然希望允许继承,但要确保不会进一步覆盖某些方法。 One use might be to effectively template the method , eg for diagnostics:一种用途可能是有效地模板化方法,例如用于诊断:

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);

Now subclasses can't override Foo directly - they'd have to override FooImpl , so our behaviour will always be executed when other code calls Foo .现在子类不能直接覆盖Foo - 他们必须覆盖FooImpl ,所以我们的行为将始终在其他代码调用Foo时执行。

The templating could be for other reasons of course - for example to enforce certain aspects of argument validation.模板当然可能是出于其他原因 - 例如强制执行参数验证的某些方面。

In my experience sealed methods aren't used terribly often, but I'm glad the ability is there.根据我的经验,密封方法并不经常使用,但我很高兴有这种能力。 (I just wish classes were sealed by default, but that's another conversation.) (我只是希望类在默认情况下是密封的,但这是另一个对话。)

Sealed Methods密封方法

Sealed method is used to define the overriding level of a virtual method.密封方法用于定义虚拟方法的覆盖级别。

Sealed keyword is always used with override keyword. Sealed 关键字始终与 override 关键字一起使用。

Practical demonstration of sealed method密封方法的实际演示

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();
        }
    }
}

Now if you declare a subclass of Program you won't be able to override the Test method, that's the point.现在,如果您声明 Program 的子类,您将无法覆盖 Test 方法,这就是重点。

In most cases you won't need sealed methods but they can prove themselves useful when you're developing a base class for some plugin system that third-party developers have to extend in order to create their own plugin.在大多数情况下,您不需要密封方法,但是当您为某些插件系统开发基类时,它们可以证明自己很有用,第三方开发人员必须扩展这些基类才能创建自己的插件。 You can keep some service data like plugin name and whether it is enabled and use sealed methods and properties to do it, so plugin developers won't mess with it.您可以保留一些服务数据,例如插件名称和是否启用,并使用密封的方法和属性来完成,这样插件开发人员就不会乱七八糟。 That's one case when sealed members come handy这是密封成员派上用场的一种情况

First of all, let's start with a definition;首先,让我们从定义开始; sealed is a modifier which if applied to a class make it non-inheritable and if applied to virtual methods or properties makes them non-ovveridable . Sealed 是一个修饰符,如果应用于类,则使其不可继承,如果应用于虚拟方法或属性,则使其不可超越

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

An example of its usage is specialized class/method or property in which potential alterations can make them stop working as expected (for example, the Pens class of the System.Drawing namespace).其用法的一个示例是特殊的类/方法或属性,其中潜在的更改可以使它们按预期停止工作(例如,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; }
        ...
    }
}

Because a sealed class cannot be inherited, it cannot be used as base class and by consequence, an abstract class cannot use the sealed modifier .因为密封类不能被继承,它不能用作基类,因此抽象类不能使用密封修饰符 It's also important to mention that structs are implicitly sealed .同样重要的是要提到结构是隐式密封的

Example例子

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 documentation微软文档

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

C# has it because Java has an identical feature ( final methods). C# 有它是因为 Java 有一个相同的特性( final方法)。 I've never seen a legitimate use.我从未见过合法用途。

If you don't want to permit extension, the whole class should be marked sealed and not just one method.如果您不想允许扩展,则应将整个类标记为已sealed ,而不仅仅是一种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM