条件语句,通用委托不必要转换类型。

8

我在设置 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;
    }

也许你可以把这个问题理解为,为什么需要使用cast呢?
4个回答

2
您正在混淆两个类似的概念:
A)方法组。方法组是一个或多个具有相同名称的C#方法。它是编译器主要使用的抽象;您无法传递方法组。您可以对方法组进行调用或将其创建为委托。如果类型签名匹配,您可以从方法组隐式创建委托。
B)委托。您知道什么是委托;它具有特定的类型签名并直接引用方法。除了调用它之外,您还可以传递它并将其视为一等对象。
因此,在第一个示例中,您的表达式在一侧返回方法组B,另一侧返回另一个方法组C。三元运算符需要在两侧返回相同的类型,但它不知道如何将任一侧转换;您分配结果的变量类型(Action<bool>)不确定表达式的类型。因此它是模棱两可的。
在第二个示例中,您合法地将方法组B转换为三元运算符的一侧的Action<bool>委托。在试图消除表达式的歧义时,编译器尝试将每一侧转换为另一侧的类型。它可以成功地将方法组C转换为Action<bool>,因此它这样做,表达式是合法的。

1

因为BC实际上不是委托。它们是方法组,可以隐式转换为委托(特别是Action<bool>),但这并不是同一件事。

条件表达式的类型必须在两个分支上保持一致,由于BC目前是方法组(未经过类型化),编译器无法确定类型应该是什么。正如它告诉你的那样,它们之间没有隐式转换。

此外,它不能(或者至少不会)看向赋值运算符的另一侧并说“哦,它应该是Action<bool>”。

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


0

我认为,Eric会再次告诉我,我的推理略有不妥, 但我仍然会尝试并期待他的纠正 :-)

一个方法组,例如B,没有类型,它不是一个对象(B.GetType()不会编译)。
它可以轻松地转换为一种类型,这就是为什么存在隐式转换。 示例:

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

然而,正如您在链接的问题中所看到的那样,三元表达式试图找到两个表达式匹配的返回类型。它不知道稍后应该发生到 Action<bool> 的转换。因为方法组本身并不是类型,所以它们之间不存在转换,B 无法转换为 C,因此编译器会抱怨。

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


-1

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接