设置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;
}
所以也许你可以阅读这个问题,为什么演员必要?
答案 0 :(得分:2)
你把两个相似的概念混为一谈:
A)方法组。方法组是一个或多个具有相同名称的C#方法。它是一个主要由编译器使用的抽象;你无法传递一个方法组。您可以使用方法组执行的任何操作都可以调用它或从中创建委托。如果类型签名匹配,您可以隐式地从方法组创建委托。
B)代表。你知道代表是什么;它具有特定的类型签名并直接引用方法。除了调用它之外,您还可以传递它并将其视为第一类对象。
因此,在第一个示例中,表达式在一侧返回方法组B
,在另一侧返回另一个方法组C
。三元运算符需要在两侧返回相同的类型,但它不知道要向任何一方投射什么;您将结果分配给(Action<bool>
)的变量类型不确定表达式的类型。所以这很模糊。
在第二个示例中,您合法地将方法组B
强制转换为三元运算符一侧的Action<bool>
委托。在尝试消除表达式歧义的过程中,编译器尝试将每一侧转换为另一方的类型。它可以成功地将方法组C
投射到Action<bool>
,因此它会这样做并且表达式是合法的。
答案 1 :(得分:1)
因为B
和C
实际上不是代理人。它们是方法组,它们可以被隐含地转换为代理(特别是Action<bool>
),但这不是一回事。
条件表达式的类型必须在两个分支上保持一致,并且由于B
和C
当前是方法组(未键入),编译器无法弄清楚类型是什么应该。正如它告诉你的那样,它们之间没有隐含的转换。
同样,它不能(或者至少不)查看赋值运算符的另一端并说“哦,它应该是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是一个特定的委托类,并且没有从具有类似签名的常规委托可用的隐式转换。