CS0311: The type 'type1' cannot be used as type parameter 'T' in the generic type or method ''. There is no implicit reference conversion from 'type1' to 'type2'.
I have these two classes to start off with:
public abstract class Node<N> where N : Node<N> { ... }
public class Pathfinder<N> where N : Node<N> { ... }
Then, I have an implementation of Node called Node2D that takes a different generic type, which must extend another class called World.
public abstract class World<W> where W : World<W> { ... }
public class Node2D<W> : Node<Node2D<W>> where W : World<W> { ... }
I can create an object of type Pathfinder< Node2D< TestWorld > > without any issue (see below). However, when I try to create a Pathfinder using types that extend Node2D< TestWorld >, VSC gives me a CS0311 error. This happens when I make the following specific classes:
public class TestWorld : World<TestWorld> { ... }
public class TestNode : Node2D<TestWorld> { ... }
// inside some function
Pathfinder<TestNode> pathfinder = new Pathfinder<TestNode>(); // gives CS0311 error where type1 is TestNode, and type2 is Node<TestNode>
And it also happens when I make a class to contain the specific implementation of Pathfinder
public class Pathfinder2D<X, W> where X : Node2D<W> where W : World<W> {
private Pathfinder<X> _pathfinder; // gives CS0311 error where type1 is X, type2 is Node<X>
}
How come the original Pathfinder will work for type Node2D< W > for any W, but not for specific implementations of Node2D< W >? If no extensions of generic types were allowed at all, I thought that Node2D< W > would also not work and one could only use the original Node< N > as a type for Pathfinder< N >. Since that worked, I then thought that so long as I have an implementation of Node2D with a specific W, that should work just as well with Pathfinder< N >. If Pathfinder< Node2D< TestWorld > > works, why doesn't Pathfinder< TestNode > where TestNode is Node2D< TestWorld >?
CS0311 states that in this declaration
Pathfinder<TestNode> p;
TestNode
must be convertible to Node<TestNode>
. That's what the constraint for Pathfinder<T>
's generic argument states:
public class Pathfinder<N> where N : Node<N>
But TestNode
is derived from Node2D<Testworld>
. And according to the declaration of Node2D<T>
public class Node2D<W> : Node<Node2D<W>>
we know that TestNode
is actually a Node<Node2D<Testworld>>
. And that is not a Node<TestNode>
.
So your generic declarations and constraints are contradictionary.
This seems to be a design flaw and how to solve this depends on what you are trying to achieve.