web-dev-qa-db-ja.com

プライベートコンストラクターを持つクラスとプライベートコンストラクターを持つシールされたクラスの違いは何ですか?

AとBに違いはありますか?

クラスAにはプライベートコンストラクタがあります。

class A
{
    private A()
    { }
}

クラスBはシールされており、プライベートコンストラクターがあります。

sealed class B
{
    private B()
    { }
}
29
jannagy02

2番目の記事によると、これが唯一のコンストラクターである場合、クラスAまたはクラスBのインスタンスを作成することはできません。クラスAにはプライベートコンストラクターがあるため、保護レベルのためにそこから派生することも、派生することもできません。シール付きB。

継承(C#プログラミングガイド)

基本クラスメンバーへの派生クラスアクセス派生クラスは、基本クラスのパブリック、保護、内部、および保護内部メンバーにアクセスできます。派生クラスは基本クラスのプライベートメンバーを継承しますが、それらのメンバーにはアクセスできません。ただし、これらのプライベートメンバーはすべて派生クラスに存在し、基本クラス自体と同じ作業を実行できます。たとえば、保護された基本クラスメソッドがプライベートフィールドにアクセスするとします。継承された基本クラスメソッドが正しく機能するには、そのフィールドが派生クラスに存在する必要があります。

プライベートコンストラクター(C#プログラミングガイド)

プライベートコンストラクターは、特別なインスタンスコンストラクターです。通常、静的メンバーのみを含むクラスで使用されます。クラスに1つ以上のプライベートコンストラクターがあり、パブリックコンストラクターがない場合、他のクラス(ネストされたクラスを除く)はこのクラスのインスタンスを作成できません。

5
Harrison

コード分​​析では、小さな違いが1つあります。

このコードを考えてみましょう:

public class Base
{
    public virtual void Function()
    {
    }
}

public class Derived: Base
{
    public static  Derived Create()
    {
        return new Derived();
    }

    private Derived()
    {
        // Code analysis warning: CS2214 "Do not call overridable methods in constructors".
        Function(); 
    }
}

Derivedコンストラクターから仮想メソッドにアクセスしているため、Derivedコンストラクターのコード分析警告があります。これはA Bad Thingです。

ただし、Derivedをシールすると、コード分析の警告は消えます。

ですから、あなたにとって小さな、そしてcontrivedの違いがあります。 ;)

5
Matthew Watson

sealedクラスはインスタンス化できますが、プライベートコンストラクターを持つクラスはインスタンス化できません。どちらも継承を許可していませんが、プライベートコンストラクターの目的ではありません。

プライベートコンストラクターを使用する理由は、インスタンス化を停止するためです。これは、インスタンスを作成するためにMyClass::Create(...)を呼び出す必要がある静的なファクトリメソッドでよく使用されます。

これは、継承を停止する封印とは関係ありません。プライベートコンストラクターを使用して継承を停止すると、間違ったアプローチが使用されます。継承用のプライベートコンストラクターを回避する方法があります。

1
Reactgular

クラスがシールされている場合、それから派生するクラスを定義することはできません。プライベートコンストラクターを持つクラスは、クラス内のファクトリーメソッドによってインスタンス化されることも、ネストされたクラスによって継承されることもありません(アクセスレベルとコンストラクターによっては、外部コードから継承される場合があります)。さらに、任意の外部コードがdeclareから派生し、new()制約を満たすクラスである可能性があります。派生クラスが基本コンストラクターを呼び出せない場合、その独自のコンストラクターは例外、クラッシュ、またはハングをスローする以外に選択肢はありませんが、そのような動作は、実際にインスタンスを構築しようとするまで検出できません。コードは正常にコンパイルされます。

0
supercat
public class Test
{


    private Test()
    {
        Debug.WriteLine("private constructor has been called in class Test");
    }

    public virtual string Run()
    {
        return "Test.Run";
    }

    public static Test GetTestRequest()
    {
        return new Test(); 
    }

    public static DerivedTest GetDerivedTestRequest()
    {
        return new DerivedTest();
    }

    public class DerivedTest:Test
    {
        public DerivedTest()
        {
            Debug.WriteLine("public constructor has been called in derived class DerivedTest.");
        }

        public override string Run()
        {
            return "DerivedTest.Run";
        }
    }
}

Debug.WriteLine(Test.GetTestRequest()。Run()); Debug.WriteLine(Test.GetDerivedTestRequest()。Run());

================================================== ==========出力:

クラスTest Test.Runでプライベートコンストラクターが呼び出されました

プライベートコンストラクターがクラスTestで呼び出されましたパブリックコンストラクターが派生クラスDerivedTestで呼び出されました。 DerivedTest.Run

そのため、ネストされたクラスは、唯一のプライベートコンストラクターを持つ外部基本クラスから派生できます。

0
Jacob