无约束类型参数铸造

时间:2015-06-22 11:13:28

标签: c# .net types casting

我的情况:

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);
    }
}

这给了我一个错误:Cannot cast expression of type 'T' to type 'T2'(或Cannot convert type 'T' to 'T2'

我理解这是因为T或T2都不受class约束,但如果我知道 - 由于IsAssignableFrom - 我可以在需要T2的地方使用T,我怎么能说服编译器允许吗?

1 个答案:

答案 0 :(得分:3)

编译器会看到T2和T标识符,并有助于通知您这些类型似乎无关。这是绝对正确的,因为它们没有任何关系:没有通用约束可以断言它们之间的任何关系(我不是说这在这里有用:)但是。

这是否是一个好的功能,是有争议的。有时候我希望它只是一个警告,但在大多数情况下,让它成为编译错误会很有帮助。泛型类中此类强制转换的数量远低于“普通”代码中拼写错误的数量:)

解决方案非常简单。只是欺骗编译器对类型一无所知,它将跳过针对目标类型的类型层次结构检查:

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

或在一个班轮中:

T2 teeTwo = (T2)(object)theTee;

类似地,您可以使用dynamic(如果您的.Net版本可用):

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

和oneliner也应该起作用:

T2 teeTwo = (dynamic)theTee;

虽然我从未尝试过那个,但我认为它比cast-via-object更重。我没有检查对象/动态方法的性能。只是预感。