web-dev-qa-db-ja.com

C#のシールドメソッド

私はC#の初心者です。Sealedキーワードについて読んでいます。Sealedクラスについて知っています。Sealedメソッドを作成できるSealedメソッドについての行を読みました。行は(メソッドを封印済みとして宣言することにより、このメソッドのオーバーライドを避けることができます。)デモを作成しましたが、上記の行と封印されたメソッドの意味が使用されることを理解していません。以下は私のコードです:-

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


}

封印された方法を使用する理由と、封印された方法の利点を教えてください。

35
Mohit Kumar

さて、あなたは2つのレベルの継承のみでテストを行っており、メソッドを「さらにオーバーライドする」という点に到達していません。 3つにすると、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.
}
69
Mehrdad Afshari

封印されたclassは、他の派生クラスの基本クラスにはなれないクラスです。

封印されていないクラスの封印されたmethodは、このクラスの派生クラスでオーバーライドできないメソッドです。

なぜ密閉方式を使用するのですか?密閉法の利点は何ですか?

さて、なぜ仮想メソッドを使用するのですか? クラスの動作をカスタマイズできるポイントを提供する。それでは、なぜ密封された方法を使用するのですか? このメソッドに関して派生クラスの動作に変更が発生しないことを保証するポイントを提供するため

クラスの動作をカスタマイズできるポイントは、usefulbutdangerous 。これらは、派生クラスが基本クラスの動作を変更できるようにするため便利です。彼らは危険です...待ってください...派生クラスが基本クラスの動作を変更できるようにするためです。仮想メソッドを使用すると、基本的に、サードパーティがクラスに、予想もテストもしたことのないクレイジーなことをさせることができます。

私が予想し、テストしたことを行うコードを書くのが好きです。メソッドを封印すると、クラスの一部をオーバーライドし続けることができ、さらに封印されたメソッドに、さらにカスタマイズできないテスト可能な安定した動作が保証されます。

69
Eric Lippert

さて、派生クラスでメソッドをさらにオーバーライドしたくない場合にのみ、methodで「sealed」を使用します。メソッドは、仮想として宣言されておらず、別の仮想メソッドをオーバーライドしない場合、デフォルトでシールされます。 (Javaでは、メソッドはデフォルトで仮想です-「デフォルト」のC#動作を実現するには、メソッドをfinalとしてマークする必要があります。)

個人的には、継承を慎重に制御するのが好きです。可能な限りクラス全体を封印することを好みます。ただし、場合によっては継承を許可したいが、someメソッドがそれ以上オーバーライドされないことを確認してください。 1つの用途は、効果的に メソッドをテンプレート化 にすることです。診断用:

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をオーバーライドする必要があるため、動作はalwaysになります他のコードがFooを呼び出すときに実行されます。

テンプレートは、もちろん他の理由である可能性があります-例えば、引数検証の特定の側面を強制するためです。

私の経験では、封印されたメソッドはそれほど頻繁に使用されることはありませんが、その機能があることを嬉しく思います。 (クラスがデフォルトでシールされることを望んでいますが、それは別の会話です。)

20
Jon Skeet

Programのサブクラスを宣言すると、Testメソッドをオーバーライドできなくなります。それがポイントです。

ほとんどの場合、封印されたメソッドは必要ありませんが、独自のプラグインを作成するためにサードパーティの開発者が拡張する必要のあるプラグインシステムの基本クラスを開発している場合、それらは有用であることがわかります。プラグイン名や有効化されているかどうかなどのサービスデータを保持し、シールされたメソッドとプロパティを使用してそれを行うことができるため、プラグイン開発者はそれを台無しにできません。密封されたメンバーが便利になるときの1つのケースです

1
Dyppl

密閉されたメソッド

シールドメソッドは、仮想メソッドのオーバーライドレベルを定義するために使用されます。

シールドキーワードは、常にオーバーライドキーワードとともに使用されます。

密閉法の実践的デモンストレーション

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