C#编译器歧义调用错误:匿名方法与方法组
C# 提供两种调用函数的语法:匿名方法(或 lambda 语法)和方法组。当一个函数有多个重载,接受不同的委托类型时,使用方法组语法可能会出现歧义。
考虑以下代码示例:
<code class="language-csharp">class Program { public static void Main() { // 匿名方法(编译成功) Method(() => classWithSimpleMethods.GetString()); Method(() => classWithSimpleMethods.DoNothing()); // 使用显式转换的方法组(也编译成功) Method((Func<string>)classWithSimpleMethods.GetString); Method((Action)classWithSimpleMethods.DoNothing); // 方法组(错误:“歧义调用”) Method(classWithSimpleMethods.GetString); Method(classWithSimpleMethods.DoNothing); } public static void Method(Func<string> func) { /* 执行某些操作 */ } public static void Method(Action action) { /* 执行某些操作 */ } }</code>
在这个例子中,Method
函数有两个重载,一个接受 Action
,另一个接受 Func<string>
。当使用匿名方法或显式转换为正确的委托类型调用函数时,代码可以编译而不会出错。但是,当使用方法组语法时,编译器会报告“歧义调用”错误。
理解歧义
C# 语言规范指出,从方法组到兼容的委托类型存在隐式转换。但是,在这种情况下,编译器面临歧义,因为方法组 classWithSimpleMethods.GetString
可以隐式转换为 Func<string>
和 Action
。
根据规范,重载解析涉及根据匹配的参数类型选择最适用的候选者。虽然 GetString
方法的参数列表与两个重载都兼容,但编译器无法确定最佳匹配,因为它在重载解析期间不考虑返回类型。
解决歧义
为了解决歧义,可以使用显式转换为正确的委托类型,如代码示例所示。但是,这种方法可能很繁琐且容易出错。
幸运的是,在 C# 7.3 及更高版本中,编译器已经改进以处理这种情况。现在,根据与目标委托类型的兼容性对重载候选者进行排名,从而在这种情况下无需显式转换。
以上是为什么 C# 在使用方法组而不是匿名方法时会抛出'不明确的调用”错误?的详细内容。更多信息请关注PHP中文网其他相关文章!