this must be such a common scenario that there’s been a lot written about it already, hopefully even a really good pattern. I have a domain model in which a custom container contains entities. For example (properties and interfaces excluded for brevity):
class Entity
{
public int Id;
public EntityContainer ParentContainer;
}
class EntityContainer
{
public int Id;
public IList<Entity> Entities = new List<Entity>();
public void AddEntity(Entity entity)
{
entity.ParentContainer = this;
Entities.Add(entity);
}
}
class Main
{
public Main()
{
Entity entity1 = new Entity();
Entity entity2 = new Entity();
EntityContainer entityContainer = new EntityContainer();
entityContainer.AddEntity(entity1);
entityContainer.AddEntity(entity2);
// Can now traverse graph easily, e.g.
Console.WriteLine("entity1's parent container ID = " + entity1.ParentContainer.Id);
Console.WriteLine("Container contains at least this entity ID: " + entityContainer.Entities[0].Id);
}
}
I can now easily traverse my object graph both ways, but have created a circular reference. Would you create a third type to divorce the dependencies?
Thanks in advance
There’s nothing wrong with circular references, per se, and they are used extensively in the .NET Framework, e.g. XmlNode.OwnerDocument, Control.Parent.
If you need to traverse up the tree, then a back reference is fine to use.
In COM, circular references are tricky because if you were the set the container and all its children to nothing, then objects will not be cleaned up properly as the children still hold references to the parent. However the .NET garbage collection has no problem with this the way it is implemented.