jeudi 21 février 2019

How do i make a tree data structure that can hold two differnet generic types for parent and children

I am ashamed to admit that I am sitting on this problem for many many hours. But I just want to implement it the way I have it structured in the diagramm below....

I want to model the world with continents/countrys/states and citys in it. Each model has a reference to its parent and a list of references to its children except the world only has children (because there cant be a parent to it) and the city only has a parent-reference because it doesnt go deeper. (I want to implement it that for example "World" does not have a parent field, likewise "city" does not have a List < Children > field.

I was about to implement it in a tree data structure like following (I left out the implementations): Only interfaces shown for simplicity

To give you an idea of the code of the interfaces I included the bare minimum of it here:

public interface IRoot<TChild>
{
    List<TChild> Children { get; set; }
    void AddChild(TChild child);
}
public interface ILeaf<TParent>
{
    TParent Parent { get; set; }
}
public interface INode<TParent, TChild> : IRoot<TChild>, ILeaf<TParent> { }

And a little code of the implementation:

public class Root<TChild> : IRoot<TChild>
{
    public List<TChild> Children { get; set; }
    public void AddChild(TChild child) { //... }
}
public class Leaf<TParent> : ILeaf<TParent>
{
    public TParent Parent { get; set; }
}
public class Node<TParent, TChild> : INode<TParent, TChild>
{
    private IRoot<TChild> root;
    private ILeaf<TParent> leaf;

    //...
}

Lastly the code of the classes I want to structure:

public class World : Root<Continent> { }
public class Continent : Node<World, Country> { }
public class Country : Node<Continent, State> { }
public class State : Node<Country, City> { }
public class City : Leaf<City> { }

Here comes the Problem:

Now to Add a child object in Root.AddChild(TChild) I need to access < TChlid >.Parent so I would need to constraint the generic TChild to "ILeaf< IRoot < TChild >>" like this:

public class Root<TChild> : IRoot<TChild> where TChild : ILeaf<Root<TChild>>
{
    public void AddChild(TChild child)
    {
        child.Parent = this;
    }
}

But doing this, I get the Error

CS0311 C# The type cannot be used as type parameter in the generic type or method. There is no implicit reference conversion from to.

At this line

public class World : Root<Continent> { }

If anyone can help me figure the problem out and find a solution I would sooo appreciate it

Aucun commentaire:

Enregistrer un commentaire