【问题标题】:Generics, abstract classes, constructors泛型、抽象类、构造函数
【发布时间】:2009-08-26 10:35:18
【问题描述】:

我有一个抽象基类

class AbstractClass 
{
    Col<AbstractClass> parent

    public AbstractClass()
    {
        //do stuff
    }
}

我有两个实现

class A : AbstractClass 
{ 
    Col<A> parent

    public A(Col<A> parent)
        :base(parent)
    {
        this.parent = parent;
    }  

}

class B : AbstractClass 
{ 
    Col<B> parent

    public B(Col<B> parent)
        :base(parent)
    {
        this.parent = parent;
    }
}

我有一个收藏

class Col<T> : IList<T> where T : AbstractClass

在另一个类中使用Col&lt;A&gt; and Col&lt;B&gt;,我们称这个类为C。

class C
{
    List<A> a = new List<A>()
    List<B> b = new List<B>()
}

这一切都会奏效,除了我希望类型 A 和 B 了解它们的父集合。我认为在AbstractClass, A, B 中有以下构造函数是可以的,但似乎通用约束仅适用于类而不适用于方法。基本上我想要以下构造函数:

public AbstractClass(Col<T> where T : AbstractClass)
public A(Col<A>)
public B(Col<B>)

A、B 的实例需要知道它们在哪个集合中,但我不能从派生类调用基构造函数,因为它们是不同的类型。

救命!

【问题讨论】:

    标签: c# generics collections constructor


    【解决方案1】:

    当我想做这样的事情时,我经常使用与 C++ curiously recurring template pattern 相关的模式:

    abstract class AbstractClass<TDerivedClass>
        where TDerivedClass : AbstractClass<TDerivedClass>
    {
        Col<TDerivedClass> parent;
    
        public AbstractClass(Col<TDerivedClass> parent)
        {
            // do stuff
            this.parent = parent;
        }
    }
    
    class A : AbstractClass<A>
    { 
        public A(Col<A> parent)
            :base(parent) {}
    }
    
    class B : AbstractClass<B>
    { 
        public A(Col<B> parent)
            :base(parent) {}
    }
    

    【讨论】:

      【解决方案2】:

      使用自定义 Collection&lt;T&gt; 类型而不是 List&lt;T&gt;。它们基本上提供相同的功能(Collection&lt;T&gt; 在内部使用 List&lt;T&gt;),并且正是为此目的而设计的。

      然后您可以覆盖 InsertItem 以设置添加到集合中的任何项目的父项。

      public class MyCollection<T> : System.Collections.ObjectModel.Collection<T>
      {
          protected override void InsertItem(int index, T item)
          {
              base.InsertItem(index, item);
              item.Parent = this;
          }
      }
      

      【讨论】:

      • 那么,取消构造函数?
      • @Matt:为了简洁,我没有将构造函数包括在内。当然,您需要添加链接到基本构造函数的构造函数。
      • 我已经编辑了我的问题以更好地解释我的问题。不过,我认为我们在正确的轨道上
      • @Matt:您可以使用new 关键字将Col&lt;AbstractClass&gt; 属性隐藏在基类中,或者保持原样并强制转换。但是你不能覆盖,这是你必须忍受的。
      • 另外,请注意,您可以对方法/构造函数进行泛型类型约束。例如public void Foo&lt;T&gt;(T bar) where T : AbstractClass { ... }
      【解决方案3】:

      我希望类型 A 和 B 知道他们的父集合

      您可能对this article 感兴趣。我写它时考虑了 XML 序列化,但它可以在更一般的上下文中使用

      【讨论】:

        【解决方案4】:

        据我了解,这不能在 C#2.0 中完成。该功能已经存在于 CLR 中,但 C# 不允许。在 C# 2.0 中,我们有不变的泛型。在 C# 4.0 中将支持变体。

        这是我的参考资料:

        http://blogs.msdn.com/rmbyers/archive/2005/02/16/375079.aspx

        http://code.msdn.microsoft.com/csharpfuture

        http://channel9.msdn.com/pdc2008/TL16/

        我说的对吗?

        【讨论】:

          猜你喜欢
          • 2020-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-24
          • 2012-01-16
          • 2016-08-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多