条件语句、泛型委托不需要强制转换

本文关键字:不需要 转换 语句 泛型 条件 | 更新日期: 2023-09-27 18:05:58

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

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

在'method group'和'method group'之间没有隐式转换

这很奇怪,因为我不明白为什么这是非法的。

顺便说一下,下面的语法将使其有效(从编译器的角度来看):
    public void A()
    {
        Action = Foo ? (Action<bool>) B : C;
    }

所以也许你可以把这个问题理解为,为什么需要演员阵容?

条件语句、泛型委托不需要强制转换

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

A)方法组。方法组是一个或多个具有相同名称的c#方法。它是一个抽象概念,主要由编译器使用;你不能传递方法组。对方法组所能做的就是调用它或从中创建一个委托。如果类型签名匹配,可以从方法组隐式创建委托。

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

所以在第一个例子中,表达式在一边返回一个方法组B,在另一边返回另一个方法组C。三元操作符需要在两边返回相同的类型,但它不知道将两边强制转换为什么;给结果赋值的变量类型(Action<bool>)不能决定表达式的类型。所以这是有歧义的

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

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

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

同样,它不能(或者至少不能)看着赋值操作符的另一边说"哦,它应该是Action<bool>"。

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

我想,Eric会再次告诉我,我的推理有点不正确,但我还是会试一试,希望他能纠正:-)

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

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

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

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

Action是一个特定的委托类,并且没有从/到具有类似签名的常规委托的间接转换。