I have two classes. First class is Parent
, which has a list of objects (Child
). Each of the Child
has the reference to his Parent
class. Question is how to implement this reference through the constructor.
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; }
}
The issue is that I have a code which parses some XML code and creates the list of Parent
objects. Here is the example:
internal Parent ParseParent(XElement parentXElement)
{
return new Parent(parentXElement.Attribute("id").Value, parentXElement.Attribute("name").Value, parentXElement.Descendants("child").Select(ParseChild));
}
Of course I can init the Parent
property within Parent
constructor, just remove the private
from Parent
setter and then go trhough all children and use this property. But I want to make it read-only. Something like this:
public Parent(string id, string name, IEnumerable<Child> children)
{
Id = id;
Name = name;
Children = children.ForEach(c => c.ParentInstance = this);
}
To be immutable and include cyclic references, you'd need something like this:
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;
}
}
The comment in the Child
constructor is the bit that should make you raise your eyebrows. Even though Parent
is immutable, we're leaking this
before we've finished initializing it... so the Child
constructor needs to make sure it doesn't try to find its siblings during construction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With