带有泛型的嵌套类

本文关键字:嵌套 泛型 | 更新日期: 2023-09-27 17:57:50

我目前正在进行的项目要求我创建一个树数据结构。以下是我如何尝试实现此功能的示例。我决定创建一个子节点集合作为嵌套类,因为它允许我在它的Add()方法中设置Nodes parent,同时保持parent-setter私有,这样从node派生的类或同一程序集中的其他类就无法直接访问它。

class Node<T> where T : Node<T>
{
  private T mParent;
  private ChildNodeCollection<T> mChildren;
  public T Parent
  {
    get{return this.InnerParent;}
  }
  private T InnerParent
  {
     get{return this.mParent;}
     set {this.mParent = value;}
  }
  public Node()
  {
      this.mChildren = new ChildNodeCollection<T>(this);
  }
  class ChildNodeCollection<U> where U : T
  {
       private U mParent;
       public U CollectionParent
       {
           get{return this.mParent;}
       }
       public ChildNodeCollection(U parent)
       {
           this.mParent = parent;
       }

        public void Add(U item)
        {
            item.InnerParent = this.CollectionParent;
            ...
        }
  }
}

不过,此代码不可编译。它抱怨Node构造函数中的this.mChildren = new ChildNodeCollection(this)行。它抛出了这两个错误。

Error   35  The best overloaded method match for Node<T>.ChildNodeColllection<T>.ChildNodeColllection(T)' has some invalid arguments
Error   36  Argument '1': cannot convert from Node<T> to T

我想它不可能证明t是Node,尽管我在类定义中指定了它。我很好奇是否有人知道如何以不同的方式完成这项工作,这样我就可以在将Node添加到集合时设置它的父级,而不会用内部访问修饰符过多地暴露Node的parent属性。

带有泛型的嵌套类

在任何情况下,使用构造函数创建泛型对象时都需要显式指定类型参数,因此需要编写以下内容:

this.mChildren = new ChildNodeCollection<T>(this);

这不会起作用,因为this的类型是Node<T>,而不是T(这是构造函数所需要的)。我认为修复它的最简单方法是将父级存储为Node<T>,而不是使用泛型参数。

代码的相关部分如下所示:

public Node() {
  this.mChildren = new ChildNodeCollection(this);
}
class ChildNodeCollection {
  private Node<T> mParent;
  public ChildNodeCollection(Node<T> parent) {
    this.mParent = parent;
  }
}

我想您最初的目标(使用T : Node<T>约束)是使用继承来定义更特定类型的节点。然后,您希望检索静态类型为T(即您的特定节点类型)的子节点(或父节点)。我可能错了,但我非常怀疑这是否可以用.NET泛型来表达。

我认为使用Node<T>作为表示包含T类型值的节点的类型要容易得多,而不是使用继承。

您正在指定一个约束,该约束表示U必须继承自T

当您尝试执行this.mChildren = new ChildNodeCollection(this)U时,它被隐式定义为该类型(Node<T>)。但是T没有定义。

我相信使用protected 可以解决这个问题

class Node<T> 
{
    protected Node<T> _parent;
    protected List<Node<T>> _children;
    protected T _value;
    protected Node() { }
    public Node(T value)
    {
        _parent = null;
        _value = value;
        _children = new List<Node<T>>();
    }
    public void AddChild(Node<T> child) 
    {            
        child._parent = this;
        _children.Add(child);
    }
}
class NaughtyNode : Node<int>
{
    //Naughty nodes dont have parents, only kids
    public NaughtyNode(int value)
    {
        _value = value;
        _children = new List<Node<T>>();
    }
    public void BeNaughty()
    {
        Node<int> victim = new Node<int>(1);
        victim._parent = this; //Does not work, cannot access
    }
    public void AddChild(NaughtyNode child)
    {
        _children.Add(child);
    }
}

protected只允许Node<T>中的代码访问它。NaughtyNode看不到Node<T>_parent