首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我只能使用"as“强制转换逆变委托。

我只能使用"as“强制转换逆变委托。
EN

Stack Overflow用户
提问于 2012-12-11 11:50:10
回答 3查看 777关注 0票数 28

我试图转换一个逆变委托,但由于某些原因,我只能使用"as“运算符。

代码语言:javascript
复制
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会导致错误:

代码语言:javascript
复制
Cannot convert type 'delegateCovariance.MyFuncType<myNamespace.MyInterface>' to myNamespace.MyFuncType<T>'

MSDN article on the as operator声明castFunc2和castFunc3是“等价的”,所以我不明白它们中的一个怎么会导致错误。另一件让我困惑的事情是,将MyInterface从接口更改为类可以消除错误。

有人能帮我理解一下这里发生了什么吗?谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-11 13:54:05

添加一个约束,使T必须是一个类。

代码语言:javascript
复制
class MyClass<T> where T: class, MyInterface

这为编译器提供了足够的信息,使其知道T是可转换的。您也不需要显式强制转换。

差异仅适用于引用类型。允许T是没有约束的值类型,这会破坏编译器证明T是逆方差兼容的能力。

第二条语句之所以有效,是因为as实际上可以执行null转换。例如:

代码语言:javascript
复制
class SomeClass { }
interface SomeInterface { }
static void Main(string[] args)
{
   SomeClass foo = null;
   SomeInterface bar = foo as SomeInterface;
}

显然,Foo不能直接转换为SomeInterface,但它仍然成功,因为仍然可以进行null转换。您的MSDN参考可能在大多数情况下都是正确的,但生成的IL代码非常不同,这意味着从技术角度来看,它们是根本不同的。

票数 15
EN

Stack Overflow用户

发布于 2012-12-11 14:54:21

Eric Lippert在他最近的帖子中对这个问题做了很好的解释:An "is" operator puzzle, part oneAn "is" operator puzzle, part two

此行为背后的主要原理如下:" is“(或" as ")运算符与强制转换不同。如果相应的强制转换是非法的,"as“操作符可能会导致非空的结果事件,当我们处理类型参数时尤其如此。

基本上,在你的例子中,cast运算符意味着(正如埃里克所说的)“我知道这个值是给定类型的,即使编译器不知道这一点,编译器也应该允许它”或“我知道这个值不是给定类型的;生成专用的、特定于类型的代码来将一种类型的值转换为另一种类型的值。”

后面的情况处理值转换,如双精度到整数转换,我们可以在当前上下文中忽略这一含义。

泛型类型参数在第一个上下文中也不是逻辑的。如果您正在处理泛型类型参数,那么为什么不使用泛型类型参数来清楚地说明这个“约定”呢?

我不是百分之百确定你想要实现什么,但你可以在你的方法中省略特殊类型,而自由地使用泛型参数:

代码语言:javascript
复制
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运算符,而不是类型检查。

票数 4
EN

Stack Overflow用户

发布于 2012-12-11 12:14:20

您的类说明T实现了MyInterface,因为MyInterface不是实例类型。因此,不能保证MyFuncType<T>MyFuncType<MyInterface>。它可以是MyFuncType<SomeType>SomeType : MyInterface,但这与SomeOtherType : MyInterface是不同的。讲得通?

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13813347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档