Question

I'm attempting to override a base property like so:

public class Node {}
public class SubNode : Node { }

public class NodeViewModel<T> where T : Node
{
    public virtual T Data { get; set; }
}
public class SubNodeViewModel : NodeViewModel<SubNode>
{
    public override SubNode Data { get; set; }
}

...
List<NodeViewModel<Node>> l = new List<NodeViewModel<Node>>();
l.Add(new SubNodeViewModel()); // Cannot convert from SubNodeViewModel to NodeViewModel<Node>
...

I think I must be misunderstanding a fundamental of inheritance. Why am I not able to do this?

I guess I'm confused as to why this works:

Node node;
SubNode subnode;
node = subnode; // I work just fine!

But not this:

NodeViewModel<Node> node;
SubNodeViewModel subnode;
node = subnode; // I don't work. Also, I hate you!
Was it helpful?

Solution 2

The error occurs because your NodeViewModel<T> class is not covariant. Whether you can do this depends on the operations you need to support, but for the code in your question you can create an interface:

public interface INodeViewModel<out T> where T : Node
{
    T Data { get; }
}

then implement it

public NodeViewModel<T> : INodeViewModel<T> where T : Node { ... }

then change the type of the items in l:

List<INodeViewModel<Node>> l = new List<INodeViewModel<Node>>();

OTHER TIPS

You are not able to do this because NodeViewModel<T> is not covariant on its type argument T: NodeViewModel<Node> is not the "base class" of NodeViewModel<SubNode>, even if Node is the base of SubNode. Technically this has nothing to do with inheritance.

If you want to have all kinds of NodeViewModel in the same list the only way to do that is by using a common interface or base class as the type argument of the list.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top