Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unconstrained type parameters casting

My situation:

interface ISomeInterface {
    void DoSmth<T>(T other);
}

class Base : ISomeInterface
{
    public virtual void DoSmth<T>(T other){
        // for example do nothing
    }
}

class Derived<T2> : Base {
    Action<T2> MyAction {get;set;}

    public override void DoSmth<T>(T other){
        if(typeof(T2).IsAssignableFrom(typeof(T)))
            MyAction((T2) other);
    }
}

This gives me an error: Cannot cast expression of type 'T' to type 'T2' (or Cannot convert type 'T' to 'T2')

I understand that it is because neither T or T2 are constrained with class, but if I know - due to IsAssignableFrom - that I can use T where I need T2, how can I convince compiler to allow it?

like image 919
Gerino Avatar asked Jun 22 '15 11:06

Gerino


1 Answers

The compiler sees the T2 and T identifiers and helpfully informs you that those types seem unrelated. That's absolutely correct, as they have no relation: there are no generic constraints that would assert any relations between them (I'm not saying that would be useful here though :) ).

Whether this is a good feature or not, is disputable. Sometimes I'd like it to be just a warning, but in most cases, it's helpful to have it be a compilation error. Number of such casts in generic classes is much lower than number of typos in 'normal' code :)

Solution is very very simple. Just cheat the compiler to know nothing about the source type, and it will skip the type hierarchy checks against destination type:

T theTee = ...;
object temp = (object)theTee;
T2 teeTwo = (T2)temp; // ok! 'temp' is now seen as 'object'

or in one liner:

T2 teeTwo = (T2)(object)theTee;

similarly, you can use dynamic (if it's available at your .Net version):

T theTee = ...;
dynamic temp = theTee;
T2 teeTwo = temp;

and oneliner should work too:

T2 teeTwo = (dynamic)theTee;

though I have never tried that one, as I think it's heavier than cast-via-object. I haven't checked performance of object/dynamic approaches though. Just a hunch.

like image 119
quetzalcoatl Avatar answered Oct 29 '22 23:10

quetzalcoatl