3

実装クラスの型のパラメーターを取る抽象メソッドを持つ抽象クラスを取得しました。次のようなジェネリックによってこれを実現できます。

abstract class Clazz<T>
{
   public abstract void CopyFrom(Clazz<T> source);
}

class MyClass : Clazz<MyClass>
{
  public override void CopyFrom(Clazz<MyClass>)
  {
    // implementation
  }
}

残念ながら、実装クラスの 1 つにClazz<T>要素のリストが必要です。では、どうすればこれを達成できますか?

  • 原因List<Clazz<T>>は機能しません。
  • List<Clazz<MyClass>>制限しすぎです。
  • CopyFrom()ジェネリックと抽象メソッドを削除しても機能します (私の現在の解決策) が、この方法では、実装クラスの 1 つでメソッドを実装するのを忘れる可能性があります。

編集:ここに、より詳細な例があります: 私は抽象クラスを持っています:

abstract class Clazz<T>
{
    public abstract void CopyFrom(Clazz<T> source);
    // ...
}

そして派生クラス:

class MyDerivedClass : Clazz<MyDerivedClass >
{
    public string Text;
    private readonly List<MySubClass> _list = new List<MySubClass>();

    public override void CopyFrom(MyDerivedClass source)
    {
        Text = source.Text;
    }

    private List<Clazz> GetAllItems()
    {
        List<Clazz> list = new List<Clazz>();
        list.Add(this);
        list.AddRange(_list);
    }


    private class MySubClass : Clazz<MySubClass>
    {
        public int Number;

        public override void CopyFrom(MySubClass source)
        {
            Number = source.Number;
        }
    }
}

他にもいくつかの派生クラスがあり、GetAllItems()メソッドは でのみ必要ですMyDerivedClass

4

3 に答える 3

1

これで十分でしょうか?詳細がなければ、わかりにくいです。

interface ICopyMaker
{
    void CopyFrom(ICopyMaker source);
}

abstract class Clazz<T> : ICopyMaker
{
   public abstract void CopyFrom(Clazz<T> source);

   void ICopyMaker.CopyFrom(ICopyMaker source)
   {
       var src = source as Clazz<T>;
       if (src == null) return; // know how to copy only from the instances of the same type

       CopyFrom(src);
   }
}

class MyClass : Clazz<MyClass>
{
    private List<ICopyMaker> _list = new List<ICopyMaker>();

    public override void CopyFrom(Clazz<MyClass> c)
    {
    //implementation
    }
}
于 2013-03-08T12:35:30.607 に答える
1

それぞれのメソッドをジェネリックにして、T考慮に入れる制約を導入することもできます。あなたが達成したいことをよく理解していれば、これを行うことができます:

abstract class Clazz<T>
{
   public abstract void CopyFrom(Clazz<T> source);

   public abstract void ProcessList<TDescendant>(List<TDescendant> list)
       where TDescendant : Clazz<T>;
}

class MyClass : Clazz<MyClass>
{
    public override void CopyFrom(Clazz<MyClass> source)
    {
        // implementation
    }

    public override void ProcessList<TDescendant>(List<TDescendant> list)
    {
        // implementation
    }
}

次のように、子孫にリスト処理を簡単に含めることもできます。

class MyOtherClass : Clazz<MyOtherClass>
{
    public override void CopyFrom(Clazz<MyOtherClass> source)
    {
        // implementation
    }

    // this list processing is inherited
    public override void ProcessList<TDescendant>(List<TDescendant> list)
    {
        // implementation
    }

    // this list processing is specific to this descendant only
    public void ProcessMyClassList<TDescendant>(List<TDescendant> list)
        where TDescendant : Clazz<TMyClass>
    {
        // implementation
    }
}

次に、 use は の子孫を宣言できますMyClass。これは、 であり、Clazz<T>次のようTになりMyClassます。

class MyDescendant : MyClass
{ 
}

以下の作品:

List<MyDescendant> list = new List<MyDescendant>();
new MyClass().ProcessList(list);

の場合はMyOtherClass少し事情が異なります。またはその子孫ProcessMyClassListのリストを受け入れます。Clazz<T>ただし、関連するものではなく、MyOtherClass古き良きものに関連するものMyClassです。このコードは機能します:

List<MyDescendant> list = new List<MyDescendant>();
new MyOtherClass().ProcessMyClassList(list); // this works

しかし、以下はコンパイルされません:

List<MyOtherClass> list = new List<MyOtherClass>();
new MyOtherClass().ProcessList(list);        // this works
new MyOtherClass().ProcessMyClassList(list); // this doesn't
于 2013-03-08T12:09:33.183 に答える
0

皆さんの回答に感謝しますが、私は一緒に暮らすことができる解決策を見つけたと思います.アニキフォロフの解決策のように、ジェネリックを削除してタイプチェックを追加します:

抽象クラス:

abstract class Clazz
{
   public abstract void CopyFrom(Clazz source);
}

そして派生クラス:

class MyDerivedClass : Clazz
{
    public string Text;
    private List<MyNestedClass> _list;

    public override void CopyFrom(Clazz source)
    {
        var src = source as MyDerivedClass;
        if (src == null) return;
        Text = src.Text;
    }

    public List<Clazz> GetAllItems()
    {
        var list = new List<Clazz>();
        list.Add(this);
        list.AddRange(_list);
        return list;
    }

    class MyNestedClass : Clazz
    {
        public int Number;
        public override void CopyFrom(Clazz source)
        {
            var src = source as MyNestedClass;
            if (src == null) return;
            Number = src.Number;
        }
    }
}
于 2013-03-08T14:30:44.723 に答える