Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic parent of generic child C#

I've got a parent class Container that may contain any kind of Node, where Node is a subclass of a generic class specific to the parent, like so:

public class ContainerBase<NodeType, ObjectType>
    where NodeType : NodeBase<ObjectType> where ObjectType : ObjectBase {
}

public abstract class NodeBase<T> where T : ObjectBase {
    ContainerBase<NodeBase<T>, T> container;
    public NodeBase(ContainerBase<NodeBase<T>, T> owner) {
        container = owner;
    }
}

What I want to do is create concrete subclasses for simplicity that implement standard object types:

public class ContainerNormal : ContainerBase<NodeNormal, ObjectNormal> {
}

public class NodeNormal : NodeBase<ObjectNormal> {
    //This doesn't work
    public NodeNormal(ContainerNormal owner) : base(owner) { }
}

I somewhat understand why the call to the base constructor doesn't work. It's trying to convert a ContainerNormal to a ContainerBase<NodeBase<ObjectNormal>, ObjectNormal> which doesn't really work.

So what design pattern am I missing to make this work right? Or do I just have to take in a ContainerBase<NodeBase<ObjectNormal>,ObjectNormal> in the constructor, even though it may not necessarily be a ContainerNormal object?

like image 991
Ed Marty Avatar asked Mar 09 '11 19:03

Ed Marty


People also ask

What is generic C?

Advertisements. Generics allow you to define the specification of the data type of programming elements in a class or a method, until it is actually used in the program. In other words, generics allow you to write a class or method that can work with any data type.

Is it possible to inherit from a generic type?

You can't inherit from a Generic type argument. C# is strictly typed language. All types and inheritance hierarchy must be known at compile time. . Net generics are way different from C++ templates.

What does the T designation indicate in a generic class?

T is a parameter that is associated with the generic type that is being defined in this class. To use the generic container, you must assign the type of the container by specifying it at instantiation using the angle bracket notation.


1 Answers

Explore: Covariance and contravariance, but this should work:

public class Container<TNode, T> where TNode : Node<T> { }

public abstract class Node<T>
{
    Container<Node<T>, T> container;

    public Node(Container<Node<T>, T> owner)
    {
        this.container = owner;
    }
}

public class ContainerNormal<T> : Container<Node<T>, T> { }

public class NodeNormal<T> : Node<T>
{
    public NodeNormal(ContainerNormal<T> container)
        : base(container)
    {
    }
}

public class ContainerNormal : ContainerNormal<string> { }

public class NodeNormal : NodeNormal<string>
{
    public NodeNormal(ContainerNormal container)
        : base(container)
    {
    }
}
like image 145
eulerfx Avatar answered Sep 28 '22 03:09

eulerfx