13

しばらく前に、平均的な ORM よりもはるかに単純な独自のデータ マッパーを作成したいと考えていました。そうすることで、基本クラスの継承クラスの型情報にアクセスする必要があることがわかりました。私が最初に考えたのはリフレクションでしたが、遅すぎます (ただし、リフレクションを使用する場合は、リフレクションのパフォーマンスの問題を「ほぼ」解消するFasterflectを確認してください)。

そこで、後に独自の名前があることを知ったソリューションに目を向けました: The Curiously Recurring Template Pattern です。これで問題はほとんど解決しましたが、このパターンを正しく実装する方法を学ぶのは少し大変でした。私が解決しなければならなかった2つの主な質問は次のとおりです。

1) オブジェクトが作成されたジェネリック パラメータを知らなくても、コンシューマー コードをジェネリック オブジェクトで動作させるにはどうすればよいですか?

2) C# で静的フィールドを継承するにはどうすればよいですか?

挑戦的な部分は、実際に質問を理解することでした. 自分が何をする必要があるかがわかれば、これらの質問を解決するのは非常に簡単です。CRTP が必要な場合は、これらの質問に答える必要があることに気付くでしょう... これらは密接に関連しているようです。

4

2 に答える 2

12

ジェネリック パラメーターの型を知らなくてもジェネリックを操作する

CRTP を使用する場合、「ベース」ジェネリック クラスが継承する非ジェネリック ベース クラス (可能であれば抽象的ですが、それほど重要ではありません) を使用するとよいでしょう。次に、非ジェネリック基本クラスで抽象 (または仮想) 関数を作成し、消費コードがジェネリック パラメーターを知らなくてもオブジェクトを操作できるようにします。例えば:

abstract class NonGenBase
{
    public abstract void Foo();
}

class GenBase<T>: NonGenBase
{
    public override void Foo()
    {
        // Do something
    }
}

T が何であるべきかを知らない消費コードでも、オブジェクトを基本クラスのインスタンスとして扱うことで、オブジェクトの Foo() プロシージャを呼び出すことができます。

静的フィールド継承の問題を解決する方法

CRTP を使用して問題を解決する場合、継承クラスの静的フィールドへのアクセスを提供すると有益なことがよくあります。問題は、C# では継承クラスがこれらの静的フィールドにアクセスできないことです。ただし、型名を使用する場合を除きます。私が話していることの明確な例を思いつくことができないかもしれません.1つを説明することはこの回答の範囲を超えていますが、解決策は簡単なので、ナレッジベースに隠して、必要が見つかったらそれを見つけてください.あなたはそれがそこにあることを嬉しく思います:)

class GenBase<T>: NonGenBase
{
    static object _someResource;

    protected object SomeResource { get { return _someResource; } }
}

これは、静的フィールドの継承を「シミュレート」します。ただし、ジェネリック クラスの静的フィールドは、すべてのジェネリック実装に適用されるわけではないことに注意してください。各ジェネリック実装には、静的フィールドの独自のインスタンスがあります。すべての実装で使用できる単一の静的フィールドが必要な場合は、それを非ジェネリック基本クラスに追加するだけです。

于 2012-06-07T21:09:02.457 に答える