I am implementing a generic Tree as follow:
I have a Node
class defined as:
public class Node<T>
{
public Node<T>? Parent;
public readonly Tree<T> Children;
public T? Data;
public Node() => Children = new(this);
}
And a Tree
class defined as:
public class Tree<T> : List<Node<T>>
{
protected Node<T>? _owner = null;
public Tree() { }
public Tree(Node<T>? owner) => _owner = owner;
public new void Add(Node<T> node) {
base.Add(node);
node.Parent = _owner;
}
}
Then I have a DerivedData
class that will be used to specify the generic type, implemented as:
public interface IDataRow { }
public abstract class BaseData : IDataRow { }
public class DerivedData : BaseData { }
The problem comes when I want to use it.
public class Program
{
public Program()
{
Node<BaseData> node = new Node<DerivedData>(); // This does not compile
Tree<BaseData> tree = new()
{
node
};
}
}
The assignment Node<BaseData> node = new Node<DerivedData>();
does not compile because it cannot implicitly convert Node<DerivedData>
to Node<BaseData>
.
How can I achieve this?
I tried implementing covariant and contravariant interfaces to be implemented by Node
class
public interface INodeIn<in T> { }
public interface INodeOut<out T> { }
public interface INode<T> : INodeIn<T>, INodeOut<T> { }
public class Node<T> : INode<T> { ... }
Then rewrite my main rutine as:
public Program()
{
INodeOut<BaseData> node = new Node<DerivedData>(); // Now this works...
Tree<BaseData> tree = new()
{
node // ...but this fails
};
}
When I change the data type of Tree.Add(Node<T> node)
method to be Tree.Add(INodeOut<T> node)
, other two new errors appear because INodeOut
does not contain a definition of Parent. By adding that definition neither works.