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

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

这是我的问题:

 public class Test { public bool Foo { get; set; } public Action 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) B : C; } 

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

你混淆了两个相似的概念:

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

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

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

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

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

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

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

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

我想, 埃里克会再次告诉我,我的推理有点不正确 ,但无论如何我都会尝试一下并希望他的更正:-)

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

 Action a = B; // implicit cast taking place. 

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

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

Action是一个特定的委托类,并且没有从/向具有类似签名的常规委托提供的impicit转换。