parents 和 children 的树结构
Tree structure with parents and children
我正在尝试制作 parents 和 children 的树结构。问题是我只希望能够在 child 和 parent 类 中分配 child 的 parent,而别处:
public class Parent
{
public static Parent Root = new Parent();
private List<Child> children = new List<Child>();
public ReadOnlyCollection<Child> Children
{
get { return children.AsReadOnly(); }
}
public void AppendChild(Child child)
{
child.Parent.RemoveChild(child);
child.children.Add(child);
child.Parent = this; //I need to asign the childs parent in some way
}
public void RemoveChild(Child child)
{
if (this.children.Remove(child))
{
child.Parent = Parent.Root; //here also
}
}
}
public class Child : Parent
{
private Parent parent = Parent.Root;
public Parent Parent
{
get { return this.parent; }
private set { this.parent = value; } //nothing may change the parent except for the Child and Parent classes
}
}
一位 not-C# 程序员告诉我使用 friends(比如在 C++ 中),但这些并没有在 C# 中实现,我的所有其他解决方案都失败了。
如果您还可以负责实际创建子项和父项(您可以为此提供工厂方法),则可以使用接口和私有 classes 来实现。
interface IChild
{
// methods and properties for child, including
IParent Parent { get; } // No setter.
}
interface IParent
{
// Methods and properties for parent
}
现在,您创建 IChild
的 private 实现,它也有一个父 setter。在您的代码中调用您的私有实现,但仅调用 return IChild
和 IParent
.
注意 - private classes 在 C# 中是嵌套的 classes。我无法告诉您这些 class 应该嵌套在哪个 class 中——这取决于您的项目。如果没有这样合理的地方,您可以创建一个 child/parent DLL 库,并让 internal
子级和父级 class 实现 public 接口。
顺便说一句,我不明白为什么你同时拥有 Parent
和 Child
class,尤其是不明白为什么 Child 派生自 Parent。如果你有一个 Node
class,你可以有一个 Parent
属性 和一个私人 setter,不用担心。
这可能无法回答您的问题,但它是一种替代方法。这是一个节点结构,你可以使用这样的东西:
public class Node
{
private Node _parent;
private List<Node> _children = new List<Node>();
public Node(Node parent)
{
_parent = parent
}
public ReadOnlyCollection<Node> Children
{
get { return _children.AsReadOnly(); }
}
public void AppendChild(Node child)
{
// your code
}
public void RemoveChild(Node child)
{
// your code
}
}
我看到@zmbq 刚刚编辑建议类似的内容。
如果您需要 Parent
和 Child
不同 class,那么您可以使用事件来实现。每当添加和删除 Child
时,让 Parent
class 提供一个事件,然后让 Child
监听这个事件并适当地设置它自己的父级。实际上,Parent
中的子列表成为主要数据,而父列表成为反向引用,如下所示:
public class ParentChangedEventArgs : EventArgs
{
public Parent Parent { get; private set; }
public Child Child { get; private set; }
public ParentChangedEventArgs(Parent parent, Child child)
{
this.Parent = parent;
this.Child = child;
}
}
public class Parent
{
public static event EventHandler<ParentChangedEventArgs> ParentChanged; // Could be internal or protected.
public static Parent Root = new Parent(); // SHOULDN'T THIS BE READONLY?
private readonly List<Child> children = new List<Child>();
public ReadOnlyCollection<Child> Children
{
get { return children.AsReadOnly(); }
}
public void AppendChild(Child child)
{
var oldParent = child.Parent;
if (oldParent == this)
return;
oldParent.children.Remove(child);
this.children.Add(child);
if (ParentChanged != null)
ParentChanged(oldParent, new ParentChangedEventArgs(this, child));
}
public void RemoveChild(Child child)
{
Root.AppendChild(child); // Removing a child means adding it to the root.
}
}
public class Child : Parent
{
static Child()
{
Parent.ParentChanged += new EventHandler<ParentChangedEventArgs>(Parent_ChildChanged);
}
static void Parent_ChildChanged(object sender, ParentChangedEventArgs e)
{
var child = e.Child;
child.Parent = e.Parent;
}
private Parent parent = Parent.Root;
public Parent Parent
{
get { return this.parent; }
private set { this.parent = value; }
}
}
(当然,如果它们是一样的class,那么一切都可以是私有的,这个机制就没有必要了。)
我正在尝试制作 parents 和 children 的树结构。问题是我只希望能够在 child 和 parent 类 中分配 child 的 parent,而别处:
public class Parent
{
public static Parent Root = new Parent();
private List<Child> children = new List<Child>();
public ReadOnlyCollection<Child> Children
{
get { return children.AsReadOnly(); }
}
public void AppendChild(Child child)
{
child.Parent.RemoveChild(child);
child.children.Add(child);
child.Parent = this; //I need to asign the childs parent in some way
}
public void RemoveChild(Child child)
{
if (this.children.Remove(child))
{
child.Parent = Parent.Root; //here also
}
}
}
public class Child : Parent
{
private Parent parent = Parent.Root;
public Parent Parent
{
get { return this.parent; }
private set { this.parent = value; } //nothing may change the parent except for the Child and Parent classes
}
}
一位 not-C# 程序员告诉我使用 friends(比如在 C++ 中),但这些并没有在 C# 中实现,我的所有其他解决方案都失败了。
如果您还可以负责实际创建子项和父项(您可以为此提供工厂方法),则可以使用接口和私有 classes 来实现。
interface IChild
{
// methods and properties for child, including
IParent Parent { get; } // No setter.
}
interface IParent
{
// Methods and properties for parent
}
现在,您创建 IChild
的 private 实现,它也有一个父 setter。在您的代码中调用您的私有实现,但仅调用 return IChild
和 IParent
.
注意 - private classes 在 C# 中是嵌套的 classes。我无法告诉您这些 class 应该嵌套在哪个 class 中——这取决于您的项目。如果没有这样合理的地方,您可以创建一个 child/parent DLL 库,并让 internal
子级和父级 class 实现 public 接口。
顺便说一句,我不明白为什么你同时拥有 Parent
和 Child
class,尤其是不明白为什么 Child 派生自 Parent。如果你有一个 Node
class,你可以有一个 Parent
属性 和一个私人 setter,不用担心。
这可能无法回答您的问题,但它是一种替代方法。这是一个节点结构,你可以使用这样的东西:
public class Node
{
private Node _parent;
private List<Node> _children = new List<Node>();
public Node(Node parent)
{
_parent = parent
}
public ReadOnlyCollection<Node> Children
{
get { return _children.AsReadOnly(); }
}
public void AppendChild(Node child)
{
// your code
}
public void RemoveChild(Node child)
{
// your code
}
}
我看到@zmbq 刚刚编辑建议类似的内容。
如果您需要 Parent
和 Child
不同 class,那么您可以使用事件来实现。每当添加和删除 Child
时,让 Parent
class 提供一个事件,然后让 Child
监听这个事件并适当地设置它自己的父级。实际上,Parent
中的子列表成为主要数据,而父列表成为反向引用,如下所示:
public class ParentChangedEventArgs : EventArgs
{
public Parent Parent { get; private set; }
public Child Child { get; private set; }
public ParentChangedEventArgs(Parent parent, Child child)
{
this.Parent = parent;
this.Child = child;
}
}
public class Parent
{
public static event EventHandler<ParentChangedEventArgs> ParentChanged; // Could be internal or protected.
public static Parent Root = new Parent(); // SHOULDN'T THIS BE READONLY?
private readonly List<Child> children = new List<Child>();
public ReadOnlyCollection<Child> Children
{
get { return children.AsReadOnly(); }
}
public void AppendChild(Child child)
{
var oldParent = child.Parent;
if (oldParent == this)
return;
oldParent.children.Remove(child);
this.children.Add(child);
if (ParentChanged != null)
ParentChanged(oldParent, new ParentChangedEventArgs(this, child));
}
public void RemoveChild(Child child)
{
Root.AppendChild(child); // Removing a child means adding it to the root.
}
}
public class Child : Parent
{
static Child()
{
Parent.ParentChanged += new EventHandler<ParentChangedEventArgs>(Parent_ChildChanged);
}
static void Parent_ChildChanged(object sender, ParentChangedEventArgs e)
{
var child = e.Child;
child.Parent = e.Parent;
}
private Parent parent = Parent.Root;
public Parent Parent
{
get { return this.parent; }
private set { this.parent = value; }
}
}
(当然,如果它们是一样的class,那么一切都可以是私有的,这个机制就没有必要了。)