6

すべて単一のファイル/クラスで、次のコードに出くわしました。詳細は省きますが、それは私が興味を持っている構造です。なぜ同じクラスに対して 2 つの異なる宣言があり、どのように異なるのでしょうか? 2 番目の宣言の構文の目的は何ですか?

public abstract class MyClass
{
    ...
}

public abstract class MyClass<TMyClass> : MyClass
    where TMyClass: MyClass<TMyClass>
{
    ...
}
4

5 に答える 5

3

MyClass- MyClass という名前の抽象クラス。

MyClass<TMyClass> : MyClass- という名前の抽象ジェネリック クラスMyClass<>ですが、 という名前のジェネリック型がありTMyClassます。

タイプの名前を変更すると、見やすくなります。

public abstract class MyBaseClass
{
    ...
}

public abstract class MyClass<T> : MyBaseClass
    where T: MyClass<T>
{
    ...
}
于 2013-10-10T14:29:31.247 に答える
3

異なるジェネリック アリティ (つまり、ゼロ以上のジェネリック型パラメーターの数) を持つ型は、言語によって完全に無関係であると見なされ、同じ名前を持つことができます。

これは、クラスFooを同時に持つことができることを意味します。この構文により、コンパイラーは参照先を判別できます。などを含む基本フレームワークでこれが発生することがわかります。Foo<T>Foo<T,U>ActionAction<T>

「再帰的」構造class C<T> where T: C<T>(非ジェネリックからの継承はC何も変更しないので削除しました) は、 C++ で Curiously Recurring Template Pattern (CRTP) と呼ばれるものの C# です。Eric Lippertは、ブログ投稿でこの主題を非常によくカバーしています。その結論は、これを実装する前に 2 回以上考える必要があるということです。解決できる問題はありますが、解決策には代償も伴います。

于 2013-10-10T14:30:26.653 に答える
2
public abstract class MyClass<TMyClass> : MyClass
    where TMyClass: MyClass<TMyClass>
{
    ...
}

から継承するクラスであり、から継承するMyClass必要があるジェネリック型を取りますMyClass<TMyClass>


これはあなたのための同じことのより簡単な例です

    public static void Main()
    {
        MyClass<Myclass> other = new MyClass<Myclass>(new Myclass());
        List<int> intlist = new List<int>();
    }

    public class Myclass
    {
        public Myclass()
        {
        }
        public int i { get; set; }
    }

    public class MyClass<T> where T : Myclass
    {
        T value;
        public MyClass(T val)
        {
            value = val;
        }
    }
}
于 2013-10-10T14:26:23.280 に答える
-1
 public abstract class MyClass<TMyClass> : MyClass
       where TMyClass: MyClass<TMyClass>
 {
        ...
 }

最初に指摘することは、これが別の抽象クラスから継承している抽象クラスであることです。言い換えれば、これはインスタンス化できない (別のクラスがそれを継承しない) クラスですが、継承を使用して別の抽象クラスから機能を派生させています (これは問題ありません)。

指摘する 2 番目のことは、これが型を受け入れる Template クラス (または C# で呼び出すジェネリック クラス) であることです。T が常にテンプレートになるように、慣例としてそれを T に減らしますが、何と呼ぶか​​は完全にあなた次第です。

最後に、これには一種の奇妙な制約があります。何があっても、(継承チェーンのどこかで) から継承しない限り、コンパイラはクラス型をテンプレート型として渡すことを許可しません。

 MyClass<TMyClass>

これは次の行に示されています

 where TMyClass: MyClass<TMyClass>

基本的に、これにより、このルールに従わないオブジェクトを渡すことができなくなります。

少し奇妙なのは、テンプレートによって渡された型が実際にそれ自体の型でない限り、制約がそれをテンプレートにすることはできないことを実装者に伝えていることです。このクラスの設計者 (または実装者) は、これが賢明な設計であるかどうかを判断する必要がありますが、これ自体は少し奇妙に見えます。

于 2013-10-10T14:36:16.820 に答える