条件语句、泛型委托不需要强制转换
本文关键字:不需要 转换 语句 泛型 条件 | 更新日期: 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>
,因此它这样做并且表达式是合法的。
因为B
和C
实际上不是委托。它们是方法组,它们可以隐式地转换为委托(特别是Action<bool>
),但这不是一回事。
条件表达式的类型必须在两个分支上保持一致,并且由于B
和C
目前是方法组(没有类型化),编译器无法确定应该是什么类型。正如它告诉你的,它们之间没有隐式转换。
同样,它不能(或者至少不能)看着赋值操作符的另一边说"哦,它应该是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是一个特定的委托类,并且没有从/到具有类似签名的常规委托的间接转换。