我试图转换一个逆变委托,但由于某些原因,我只能使用"as“运算符。
interface MyInterface { }
delegate void MyFuncType<in InType>(InType input);
class MyClass<T> where T : MyInterface
{
public void callDelegate(MyFuncType<MyInterface> func)
{
MyFuncType<T> castFunc1 = (MyFuncType <T>) func; //Error
MyFuncType<T> castFunc2 = func as MyFuncType<T>;
MyFuncType<T> castFunc3 = func is MyFuncType<T> ? (MyFuncType<T>)func : (MyFuncType<T>)null; //Error
}
}castFunc2工作正常,但castFunc1和castFunc3会导致错误:
Cannot convert type 'delegateCovariance.MyFuncType<myNamespace.MyInterface>' to myNamespace.MyFuncType<T>'MSDN article on the as operator声明castFunc2和castFunc3是“等价的”,所以我不明白它们中的一个怎么会导致错误。另一件让我困惑的事情是,将MyInterface从接口更改为类可以消除错误。
有人能帮我理解一下这里发生了什么吗?谢谢!
发布于 2012-12-11 13:54:05
添加一个约束,使T必须是一个类。
class MyClass<T> where T: class, MyInterface这为编译器提供了足够的信息,使其知道T是可转换的。您也不需要显式强制转换。
差异仅适用于引用类型。允许T是没有约束的值类型,这会破坏编译器证明T是逆方差兼容的能力。
第二条语句之所以有效,是因为as实际上可以执行null转换。例如:
class SomeClass { }
interface SomeInterface { }
static void Main(string[] args)
{
SomeClass foo = null;
SomeInterface bar = foo as SomeInterface;
}显然,Foo不能直接转换为SomeInterface,但它仍然成功,因为仍然可以进行null转换。您的MSDN参考可能在大多数情况下都是正确的,但生成的IL代码非常不同,这意味着从技术角度来看,它们是根本不同的。
发布于 2012-12-11 14:54:21
Eric Lippert在他最近的帖子中对这个问题做了很好的解释:An "is" operator puzzle, part one,An "is" operator puzzle, part two。
此行为背后的主要原理如下:" is“(或" as ")运算符与强制转换不同。如果相应的强制转换是非法的,"as“操作符可能会导致非空的结果事件,当我们处理类型参数时尤其如此。
基本上,在你的例子中,cast运算符意味着(正如埃里克所说的)“我知道这个值是给定类型的,即使编译器不知道这一点,编译器也应该允许它”或“我知道这个值不是给定类型的;生成专用的、特定于类型的代码来将一种类型的值转换为另一种类型的值。”
后面的情况处理值转换,如双精度到整数转换,我们可以在当前上下文中忽略这一含义。
泛型类型参数在第一个上下文中也不是逻辑的。如果您正在处理泛型类型参数,那么为什么不使用泛型类型参数来清楚地说明这个“约定”呢?
我不是百分之百确定你想要实现什么,但你可以在你的方法中省略特殊类型,而自由地使用泛型参数:
class MyClass<T> where T : MyInterface
{
public void callDelegate(Action<T> func)
{
}
}
class MyClass2
{
public void callDelegate<T>(Action<T> func)
where T : MyInterface
{
}
}否则,您应该使用带有check for null的as运算符,而不是类型检查。
发布于 2012-12-11 12:14:20
您的类说明T实现了MyInterface,因为MyInterface不是实例类型。因此,不能保证MyFuncType<T>为MyFuncType<MyInterface>。它可以是MyFuncType<SomeType>和SomeType : MyInterface,但这与SomeOtherType : MyInterface是不同的。讲得通?
https://stackoverflow.com/questions/13813347
复制相似问题