如何通过构造函数正确初始化两个类之间的父引用和子引用

Ant*_*zer 6 .net c#

我有两节课.第一类是Parent,它有一个对象列表(Child).每个人Child都提到他的Parent班级.问题是如何通过构造函数实现此引用.

public sealed class Child
{
    public Child(string id, string name, Parent parent)
    {
        Id = id;
        Name = name;
        Parent = parent;
    }

    public Parent ParentInstance { get; private set; }
    public string Id { get; private set; }
    public string Name { get; private set; }
}

public sealed class Parent
{
    public Parent(string id, string name, IEnumerable<Child> children)
    {
        Id = id;
        Name = name;
        Children = children;
    }

    public string Id { get; private set; }
    public string Name { get; private set; }
    public IEnumerable<Child> Children { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

问题是我有一个解析一些XML代码并创建Parent对象列表的代码.这是一个例子:

internal Parent ParseParent(XElement parentXElement)
{
    return new Parent(parentXElement.Attribute("id").Value, parentXElement.Attribute("name").Value, parentXElement.Descendants("child").Select(ParseChild));
}
Run Code Online (Sandbox Code Playgroud)

当然我可以ParentParent构造函数中初始化属性,只需privateParentsetter中删除然后去除所有的孩子并使用这个属性.但我想把它变为只读.像这样的东西:

public Parent(string id, string name, IEnumerable<Child> children)
{
    Id = id;
    Name = name;
    Children = children.ForEach(c => c.ParentInstance = this);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 3

要保持不可变包含循环引用,您需要这样的东西:

public sealed class Parent
{
    private readonly IEnumerable<Child> children;
    private readonly string name; // Just for example

    public Parent(XElement element)
    {
         name = (string) element.Attribute("name");
         children = element.Elements("Child")
                           .Select(x => new Child(x, this))
                           .ToImmutableList(); // Or whatever collection you want
    }
}

public sealed class Child
{
    private readonly Parent parent;
    private readonly string name; // Just for example

    public Child(XElement element, Parent parent)
    {
        this.name = (string) element.Attribute("name");
        // Better not ask the parent for its children yet - they won't be
        // initialized!
        this.parent = parent;
    }
}
Run Code Online (Sandbox Code Playgroud)

构造函数中的注释Child应该会让您大吃一惊。尽管Parent它是不可变的,但this在完成初始化之前我们就会发生泄漏......因此Child构造函数需要确保它在构造过程中不会尝试找到其兄弟姐妹。