7

実装型をインスタンス化する必要があるジェネリック クラスを作成したので、実装型にはアクセス可能なパラメーターのないコンストラクターが必要です。new() 制限が機能するように見えますが、内部にある場合は実装型にパブリック コンストラクターを強制します (ただし、両方が同じアセンブリ上にあるためアクセス可能です)。

  1. 「アクセス可能」ではなく、強制的に公開する理由はありますか?
  2. 必要なことを行う方法はありますか?

前もって感謝します。

編集:これを行う理由は、シングルトンを介して使用する必要があるクラス X があるためです。Singleton クラスはジェネリック クラスであり、外部ユーザーが間違った方法 (コンストラクターの呼び出し) でオブジェクトにアクセスするのを避けるために、クラス X コンストラクターを内部にしたいと考えています。

4

3 に答える 3

6

これは、仕様Bound and Unbound Typesのセクション 4.4.3 で概説されているように、C# 言語では許可されていません。

制約がコンストラクターの constraintnew()である場合、型はパラメーターなしのパブリック コンストラクターであってはAならず、それを持っている必要があります。abstractこれは、次のいずれかが真の場合に満たされます。

  • Aすべての値型にはパブリックの既定のコンストラクターがあるため、値型です。
  • Aコンストラクタ制約を持つ型パラメータです
  • A値型制約を持つ型パラメーターです
  • Aパラメータなしでabstract明示的に宣言されたコンストラクタを含んでいないクラスです。public
  • Aではなくabstract、デフォルトのコンストラクターがあります。

これらの条件のいずれかが満たされない場合、コンパイラ エラーが発生します。public であるが内部コンストラクターのみを持つ型があることに気付いた場合、ほとんどの場合、それらは実際には public コンストラクターを持つ内部型である必要があります。

型アクセサーをinternalに、コンストラクターを に変更しpublic、パラメーターなしにすることをお勧めします。次にpublic、パラメーターなしのコンストラクターは、パラメーターなしでないコンストラクターprivateまたはinternalコンストラクターを呼び出して、追加の初期化作業を行うことができます。

internal class C<T> where : T new()
{
    public C() : this(new T()) {
    }

    private C(T t) {
        // Do additional initialization
    }
}

パターンは限られていることに注意してください。ただし、private代わりにメソッドを使用することを妨げるものは何もありません。

internal class C<T> where T : new() {
    public C() {
        T t = new T();
        InitializeClass(t);
    }

    private void InitializeClass(T t) {
        throw new NotImplementedException();
    }
}   

あなたの更新によると、これはパブリックシングルトンパターンの小さな例です。

public class Singleton<T> where T : new()
{
    public static Singleton<T> Current {
        get;
        private set;
    }

    internal Singleton() : this(new T()) {
    }

    private Singleton(T t) {
        Current = this;
        // Do whatever you need to with T
    }        

    public String Name {
        get;
        set;
    }
}

使用法

// Somewhere in your internal assembly
Singleton<String> singleton = new Singleton<String>();

// In an external assembly
Singleton.Current.Name = "SoMoS";

そのような方法でコンストラクターを使用する必要さえありません。単純なことを同じように簡単に行うことができます。

public class Singleton<T> where T : new()
{
    public static Singleton<T> Current {
        get;
        private set;
    }

    internal Singleton() {
        T t = new T();
        // Do stuff with T
    }

    public String Name {
        get;
        set;
    }
}

要件に合わせて設計できない場合ジェネリックは適していない可能性があります。ジェネリックでできることは限られており、すべての問題を解決できるわけではありません。Factory Pattern、インジェクションなどがあります。

于 2012-05-11T11:22:16.550 に答える
2

「アクセス可能」ではなく、強制的に公開する理由はありますか?

アクセシブルという用語は非常に文脈依存であり、ジェネリックはアーキテクチャによってそうではありません。特定のケースinternalではアクセスできる可能性がありますが、ジェネリックはジェネリック ソリューション用に作成されています。

必要なことを行う方法はありますか?

最初のポイントに基づいて、いいえ、それは不可能であり、私も認識しています。

于 2012-05-11T10:34:26.457 に答える
1

ジェネリックはジェネリックソリューション用であるため、「新しい」制約を使用する場合、ソリューションはパブリックコンストラクターを実装するすべてのクラスで機能する必要があります。

特定の種類のクラスのジェネリックソリューションを実装する場合は、そのような内部コンストラクターを実装する抽象基本クラスを定義できます。この抽象基本クラスのジェネリックソリューションを実装し、

*ここで、T:MyBaseClassWithInternalCtor *

制約として。

于 2012-05-11T11:12:36.140 に答える