【发布时间】:2017-01-22 19:38:35
【问题描述】:
此代码无法编译:
using System;
using System.Runtime.CompilerServices;
static class Extensions {
public static void Foo(this A a, Exception e = null, string memberName = "") {
}
public static void Foo<T>(this A a, T t, Exception e = null, string memberName = "")
where T : class, IB {
}
}
interface IB { }
class A { }
class Program {
public static void Main() {
var a = new A();
var e = new Exception();
a.Foo(e); //<- Compile error "ambiguous call"
}
}
但如果我删除最后一个 string 参数一切都很好:
public static void Foo(this A a, Exception e = null) {
}
public static void Foo<T>(this A a, T t, Exception e = null)
where T : class, IB {
}
问题是 - 为什么这些可选的string 参数会破坏编译器对方法调用的选择?
添加: 澄清的问题:我不明白为什么编译器在第一种情况下不能选择正确的重载,而在第二种情况下可以这样做?
已编辑:
[CallerMemberName] 属性在这里不是问题的原因,所以我已将其从问题中删除。
【问题讨论】:
-
只是为了澄清:单独删除
[CallerMemberName]属性没有效果,编译器会输出错误。删除整个参数[CallerMemberName] string memberName = ""具有效果,代码编译。这是我观察到的。对吗? -
C# 规范:7.5.3.2 更好的函数成员: 否则,如果 MP 的所有参数都有对应的参数,而默认参数需要替换为至少一个可选参数MQ中的参数然后MP优于MQ。该规则适用于第二种情况,但不能适用于第一种情况。
-
如果只删除属性
[CallerMemberName],但在两种方法中都保留参数string memberName = "",会发生什么?编辑:@OndrejTucny 已经说过,我在发布后看到。还是个好问题。 -
@JeppeStigNielsen 在 LINQPad 4.57 (C# 5) 中尝试过,但无法编译。
-
@Szer 这确实是一个不明确的调用,因为 e 和 memberName 的可选参数编译器假设
T t是Exception t
标签: c#