Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call generics with base class gives cannot convert from base class to T

Tags:

c#

generics

I have the following setup and it seems that my object cannot be converted to the generic type. While it is actually the base class. Why doesn't this work? It seems so logical to me.

public class AList<T> where T : A
{
    void DoStuff(T foo)
    {
    }

    void CallDoStuff()
    {
        DoStuff(new A()); // ERROR: Cannot convert A to T
    }
}

public class A
{
}
like image 404
Marnix Avatar asked Feb 18 '13 11:02

Marnix


3 Answers

The problem here is that the constraint says that T must be A or a class derived from A.
Now, when you instantiate AList with a concrete type, T is a very specific class. And if you didn't instantiate AList with A itself but with a subclass of it, T is a subclass of A.

You can't convert an instance with a runtime type of the base class to one of its subclasses, as it misses all the information that is being added by the subclass.

Example:

public class Animal
{
    public int Foo { get; set; }
}

public class Cat : Animal
{
    public int Bar { get; set; }
}

Derived d = new Base();

Would you expect that code to work? Surely not, because a Cat is also a Animal but a Animal is not a Cat.
If you would expect the above code to actually work, ask yourself what is supposed to happen when the following code is executed: d.Bar = 42;
Animal doesn't contain a definition for Bar.

The same is happening in your code - it's just a little bit more obscured with the generics in the game.

like image 163
Daniel Hilgarth Avatar answered Nov 14 '22 03:11

Daniel Hilgarth


T could be also a class that derives from A so you can't put instance of A as a parameter of type T. Something like invoking method, that takes int with and argument that is of type object.

like image 2
Ryszard Dżegan Avatar answered Nov 14 '22 03:11

Ryszard Dżegan


This is the same reason that is an object can not be converted to int implicitly.

The method expects a child class and you are passing the parent, so you need an explicit cast.

like image 1
Ken D Avatar answered Nov 14 '22 03:11

Ken D