条件语句,泛型委托不必要的演员

时间:2011-08-16 14:04:50

标签: c# generics compiler-construction delegates

设置Action<T>值时,我在条件语句中遇到了这个非常奇怪的问题。并不是我不知道如何解决这个问题,因为使用普通的if很容易解决。

这是我的问题:

public class Test
{
    public bool Foo { get; set; }
    public Action<bool> Action { get; set; }

    public void A()
    {
        Action = Foo ? B : C;//Gives compiler error
    }

    public void B(bool value)
    {

    }

    public void C(bool value)
    {

    }
}

这给了我一个编译错误消息

  

'方法组'和'方法组'之间没有隐式转换。

这很奇怪,因为我无法弄清楚为什么这是非法的。

顺便说一下,下面的语法会使这个有效(从编译器的角度来看):

    public void A()
    {
        Action = Foo ? (Action<bool>) B : C;
    }

所以也许你可以阅读这个问题,为什么演员必要?

4 个答案:

答案 0 :(得分:2)

你把两个相似的概念混为一谈:

A)方法组。方法组是一个或多个具有相同名称的C#方法。它是一个主要由编译器使用的抽象;你无法传递一个方法组。您可以使用方法组执行的任何操作都可以调用它或从中创建委托。如果类型签名匹配,您可以隐式地从方法组创建委托。

B)代表。你知道代表是什么;它具有特定的类型签名并直接引用方法。除了调用它之外,您还可以传递它并将其视为第一类对象。

因此,在第一个示例中,表达式在一侧返回方法组B,在另一侧返回另一个方法组C。三元运算符需要在两侧返回相同的类型,但它不知道要向任何一方投射什么;您将结果分配给(Action<bool>)的变量类型不确定表达式的类型。所以这很模糊。

在第二个示例中,您合法地将方法组B强制转换为三元运算符一侧的Action<bool>委托。在尝试消除表达式歧义的过程中,编译器尝试将每一侧转换为另一方的类型。它可以成功地将方法组C投射到Action<bool>,因此它会这样做并且表达式是合法的。

答案 1 :(得分:1)

因为BC实际上不是代理人。它们是方法组,它们可以被隐含地转换为代理(特别是Action<bool>),但这不是一回事。

条件表达式的类型必须在两个分支上保持一致,并且由于BC当前是方法组(未键入),编译器无法弄清楚类型是什么应该。正如它告诉你的那样,它们之间没有隐含的转换。

同样,它不能(或者至少)查看赋值运算符的另一端并说“哦,它应该是Action<bool>”。

当您添加强制转换时,左分支表达式的类型变为Action<bool>,并且 是另一侧的方法组与该委托之间的隐式转换,因此编译器再次开心:整个表达式的类型是Action<bool>

答案 2 :(得分:0)

我想,Eric will again tell me, that my reasoning is slightly incorrect,但无论如何我都会尝试一下,并希望能够纠正: - )

方法组(例如B)没有类型,它不是对象(B.GetType()不会编译)。
它可以很容易地转换为类型,这就是存在隐式转换的原因。 样品:

Action<bool> a = B; // implicit cast taking place.

但是,正如您在链接问题中看到的那样,三元表达式尝试查找表达式的两个部分匹配的返回类型。它不知道以后会转换为Action<bool>。由于方法组本身不是类型,因此它们之间不存在转换,B无法转换为C,因此编译器会抱怨这一点。

通过将三元表达式的任何部分强制转换为Action<bool>,您告诉编译器,返回类型应该是该类型,并检查三元表达式的其他部分是否支持隐式转换为类型。因为这种情况,代码将编译。

答案 3 :(得分:-1)

Action是一个特定的委托类,并且没有从具有类似签名的常规委托可用的隐式转换。