C# 带泛型的嵌套类
我目前正在从事的项目需要我创建一个树数据结构。 下面是我如何尝试实现此功能的示例。我决定创建一个子节点集合作为嵌套类,因为它允许我在其Add()方法中设置节点父级,同时保持父级setter私有,因此从节点派生的类或同一程序集中的其他类无法直接访问它C# 带泛型的嵌套类,c#,generics,nested-class,C#,Generics,Nested Class,我目前正在从事的项目需要我创建一个树数据结构。 下面是我如何尝试实现此功能的示例。我决定创建一个子节点集合作为嵌套类,因为它允许我在其Add()方法中设置节点父级,同时保持父级setter私有,因此从节点派生的类或同一程序集中的其他类无法直接访问它 class Node<T> where T : Node<T> { private T mParent; private ChildNodeCollection<T> mChildren; publi
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;
...
}
}
}
我想它不能算出t是节点,即使我在类定义中指定了。我很好奇是否有人知道如何以不同的方式来实现这一点,使我能够在将节点添加到集合时设置其父节点,而不必使用内部访问修饰符过多地公开节点的父属性。在任何情况下,使用构造函数创建泛型对象时都需要显式指定类型参数,所以你需要写一些东西,比如:
this.mChildren = new ChildNodeCollection<T>(this);
我猜您最初的目标(使用T:Node
constraint)是使用继承来定义更具体的节点类型。然后,您希望检索静态键入为T
(即您的特定节点类型)的子节点(或父节点)。我可能错了,但我严重怀疑.NET泛型能否表达这一点
我认为将
Node
用作表示包含T
类型值的节点的类型比使用继承要容易得多 您指定的约束表示U必须从T继承
当您尝试执行此操作时,
this.mChildren=new ChildNodeCollection(this)
U被隐式定义为此(节点
)的类型。但是没有定义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);
}
}
类节点
{
受保护节点\u父节点;
受保护儿童名单;
保护T_值;
受保护节点(){}
公共节点(T值)
{
_parent=null;
_价值=价值;
_children=新列表();
}
公共void AddChild(节点子节点)
{
child.\u parent=this;
_添加(child);
}
}
类noutynode:Node
{
//淘气的节点没有父母,只有孩子
公共NoutyNode(int值)
{
_价值=价值;
_children=新列表();
}
公开无效
{
节点受害者=新节点(1);
受害者。_parent=this;//不工作,无法访问
}
public void AddChild(noutynode child)
{
_添加(child);
}
}
受保护的
仅允许节点内的代码访问它NootyNode
无法看到节点的\u父节点
Hmmm,您不应该将节点作为父节点,将节点集合作为子节点吗?还有,你不应该有一个泛型构造函数吗?如果父节点没有任何真正区别于子节点的特性,那么你可以使你想要在节点之间公开的方法受到保护,同时保持常规节点方法,如获取父节点public@FlyingStreudel具体在哪里,你能说得更具体些吗?顺便说一句,我使用的是.NET 2,因此在更高版本中添加到泛型中的任何新功能都不能使用。有关更多详细信息,请参阅我的答案,虽然它不是100%符合2.0,但我认为您在这里混用了一些东西。受保护修饰符允许访问从节点继承的所有类,因此NoutyNode可以访问并更改它的父类。Internal允许访问在同一程序集中定义的所有类,因此如果Nootynode在与Node相同的程序集中定义,则Nootynode可以更改其子集合,而无需将childrens\u parent设置为null,这可能会导致不一致。是的,我完全同意。您不想使用内部。但据我所知,NoutyNode无法访问节点的父节点。。。要快速编译测试…尝试从NoutyNode访问节点的\u父节点
会产生:无法通过类型为“StackNotebook.Node”的限定符访问受保护的成员“StackNotebook.Node.\u parent”;限定符的类型必须为“StackNotebook.NoutyNode”
Hmm。。。但我仍然不太明白为什么它不能识别Node,因为我将尝试将它更改为这个;一旦我回家。
public Node() {
this.mChildren = new ChildNodeCollection(this);
}
class ChildNodeCollection {
private Node<T> mParent;
public ChildNodeCollection(Node<T> parent) {
this.mParent = parent;
}
}
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);
}
}