我正在尝试制作父母和孩子的树形结构。问题是我只希望能够在子类和父类中对子项的父项进行设置,而不是其他任何地方:
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
}
}
一位非C#程序员,我被告知要使用朋友(比如C ++),但这些都没有在C#中实现,而我所有其他解决方案都失败了。
答案 0 :(得分:3)
如果您还负责实际创建子级和父级(您可以为此提供工厂方法),则可以使用接口和私有类来实现此目的。
interface IChild
{
// methods and properties for child, including
IParent Parent { get; } // No setter.
}
interface IParent
{
// Methods and properties for parent
}
现在,您创建了IChild
的私有实现,该实现也具有父设置器。在您的代码中调用您的私有实现,但只返回IChild
和IParent
。
注意 - 私有类是C#中的嵌套类。我不能告诉你这些类应该嵌套在哪个类中 - 这取决于你的项目。如果没有这样合理的位置,您可以创建子/父DLL库,并拥有实现公共接口的internal
Child和Parent类。
顺便说一句,我不明白你为什么同时拥有Parent
和Child
类,尤其不是为什么Child来自Parent。如果您有一个Node
类,则可以拥有一个带有私有设置器的Parent
属性,而不用担心它。
答案 1 :(得分:2)
这可能无法解答您的问题,但它可以替代。这是一个节点结构,你可以使用这样的东西:
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刚刚编辑过一些类似的东西。
答案 2 :(得分:1)
如果您需要Parent
和Child
为不同的类,则可以使用事件执行此操作。每当添加和删除Parent
时,Child
类都会提供一个事件,然后让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; }
}
}
(当然,如果他们是同一个班级,那么一切都可以是私人的,这个机制就没有必要了。)