如何使用实现类的类型的参数创建抽象方法

时间:2013-03-08 11:58:51

标签: c# generics abstract

我有一个带抽象方法的抽象类,它接受实现类类型的参数。我可以通过这样的泛型实现这一点:

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

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

不幸的是,我需要在其中一个实现类中列出Clazz<T>个元素。 那我怎么能实现这个呢?

  • 原因List<Clazz<T>>不起作用。
  • List<Clazz<MyClass>>限制性太强。
  • 删除泛型和抽象方法确实有效(我当前的解决方案),但这样我就忘记在其中一个实现类中实现CopyFrom()方法。

编辑:这里有一个更详细的例子: 我有一个抽象的课程:

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方法。

3 个答案:

答案 0 :(得分: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
    }
}

然后使用可以声明MyClass的后代,后者又是Clazz<T>TMyClass

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

答案 1 :(得分: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
    }
}

答案 2 :(得分:0)

感谢大家的答案,但我想我已经找到了一个可以忍受的解决方案: 我将删除泛型并添加一个类型检查,就像anikiforov的解决方案一样:

抽象类:

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;
        }
    }
}