In C # 4, you can accomplish this using common interface covariance:
public class ContainerBase<NodeType, ObjectType> : IContainerBase<NodeType, ObjectType> where NodeType : NodeBase<ObjectType> where ObjectType : ObjectBase { } public abstract class NodeBase<T> where T : ObjectBase { IContainerBase<NodeBase<T>, T> container; public NodeBase(IContainerBase<NodeBase<T>, T> owner) { container = owner; } } public class ContainerNormal : ContainerBase<NodeNormal, ObjectNormal> { } public interface IContainerBase<out NodeType, ObjectType> where NodeType : NodeBase<ObjectType> where ObjectType : ObjectBase { } public class NodeNormal : NodeBase<ObjectNormal> { //This doesn't work public NodeNormal(ContainerNormal owner) : base(owner) { } } public class ObjectNormal : ObjectBase {} public class ObjectBase{}
Of course, this will only work if your IContainerBase interface can avoid using any functions that will accept NodeType input. For example, this will work:
public interface IContainerBase<out NodeType, ObjectType> where NodeType : NodeBase<ObjectType> where ObjectType : ObjectBase { NodeType NodeTypeProp {get;} }
... but it will not:
public interface IContainerBase<out NodeType, ObjectType> where NodeType : NodeBase<ObjectType> where ObjectType : ObjectBase { NodeType NodeTypeProp {get;set;} // "set" not allowed on "out" type }
One more note: did you notice how I needed to specify the property “NodeTypeProp” instead of “NodeType”? This is because we do not follow C # naming conventions. You need prefix type names of type "T":
public interface IContainerBase<out TNodeType, TObjectType> where TNodeType : NodeBase<TObjectType> where TObjectType : ObjectBase
Stripling warrior
source share