Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are conversions from "class A : IX" to generic "T where T : IX" not allowed?

Why does the following cause a compilation error?

interface IX {}
interface IY {}
class XY : IX, IY {}

void Foo<T>() where T : IX, IY
{
    T xy = new XY();
    …   // ^^^^^^^^
}       // error: "Implicit conversion of type 'XY' to 'T' is not possible."

Note: The same error would occur if class XY : IX and where T : IX. However, I have chosen a more complex example because a simpler one might have provoked circumventive answers such as, "Just change the type of xy from T to IX", which would not answer why this conversion fails.

like image 610
stakx - no longer contributing Avatar asked Feb 24 '12 19:02

stakx - no longer contributing


2 Answers

Because if that were legal then you could do this:

interface IPet {} 
interface IMammal {} 
class Dog : IPet, IMammal {}  
class Cat : IPet, IMammal {}
T Foo<T>() where T : IPet, IMammal
{     
  return new Dog();
}
...
Cat cat = Foo<Cat>();  // Assigns a Dog to a variable of type Cat.
like image 151
Eric Lippert Avatar answered Oct 13 '22 21:10

Eric Lippert


Given class ABC : IX, IY { } and Foo<ABC>, would you expect to be able to use new XY() then? Because you shouldn't have that expectation. The compiler will not, either.

T is not always going to be XY. T is going to be ABC, DEF, or anything else that could implement your two interfaces and therefore meet the constraints you have. XY is not convertible to ABC, DEF, or any of the infinite possibilities for T, and therefore you have your error message: the implicit conversion of XY to T is not possible.

What would be legal there is simply new T(), and this is true only if the method is constrained to support it.

void Foo<T>() where T : IX, IY, new()
{
    T obj = new T();
}
like image 20
Anthony Pegram Avatar answered Oct 13 '22 21:10

Anthony Pegram