我的情况:
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,我怎么能说服编译器允许吗?
答案 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更重。我没有检查对象/动态方法的性能。只是预感。