这是基于 C# 5 规范,但由于 C# 6 规范似乎尚未发布,这是我能做的最好的。这也是一种援引坎宁安定律的尝试。
作为初步,在规范的 s7.5.3.1(“适用函数成员”)的语言中,两个函数成员都适用(如果另一个不存在,则可以调用它们中的任何一个)以它们的扩展形式(params object[]
不能通过string
ProductName
所以被转换为object
参数来实现)。
因此,我们继续讨论 s7.5.3.2(“更好的函数成员”),以确定两者中的哪一个是更好的函数调用。
首先,构造一个精简的参数列表 A ,其中仅包含参数表达式本身,按照它们在原始参数列表中出现的顺序排列:
{ string "ConfigName [...]", string ProductName }
接下来,每个候选函数成员的 [p] 参数列表按以下方式构建:
- 如果函数成员仅适用于扩展形式,则使用扩展形式。
- 从参数列表中删除没有对应参数的可选参数
- 参数被重新排序,以便它们出现在与参数列表中相应参数相同的位置。
这给了我们以下信息:
{ string connectionStringName, object parameter }
(optWherePart
删除,params
扩展)
{ string optWherePart, object parameter }
(params
展开)
然后,我们进行一系列比较来确定其中哪个是更好的函数成员。调用 oneMp
和 one Mq
,它们如下所示:
- 如果
Mp
是非泛型方法并且Mq
是泛型方法,则Mp
优于Mq
.
- 否则,如果
Mp
以其正常形式适用且Mq
具有 params 数组且仅适用于其扩展形式,则Mp
优于Mq
.
- 否则,如果
Mp
声明的参数多于Mq
,则Mp
优于Mq
。如果这两种方法都有params
数组并且仅适用于它们的扩展形式,则可能会发生这种情况。
- 这不是100%。我们的两个参数列表都使用原始函数定义中的 2 个参数。我认为这仅仅是为了区分两个参数进入同一个
params
数组的一种情况和一个进入数组而一个进入普通参数的情况。
- 否则,如果 的所有参数
Mp
都有对应的参数,而默认参数需要替换为至少一个可选参数,Mq
则Mp
优于Mq
.
- 啊哈!我们的第一个参数列表丢失了
optWherePart
,它需要一个默认参数,所以第二个参数列表更好!所以VS2015是错的!
... 可是等等。最后一颗子弹是什么意思?Mp
并且Mq
是特定的参数列表,其中删除了没有相应参数的 [o] 可选参数。他们中的任何一个都不可能没有相应的论点,因为如果他们没有,他们就会被删除。
总之,我无法判断这是旧编译器、新编译器……还是 C# 规范中的错误。
我发现SLaks的一篇博文似乎也认为旧行为是一个错误。该博客指出,Roslyn 已通过使编译器失败来解决此问题,而这不再是我所看到的了。也许他们改变了主意?
编辑:更新!我的Roslyn 错误报告导致了对编译器的更改,以确保在这种情况下选择第二个重载。这似乎是因为默认参数需要替换上面的措辞。我仍然认为规范是模棱两可的,所以我很失望只进行了代码更改(而不是规范更改,甚至没有讨论为什么第二个重载更好),但至少 VS2015 运行时行为是现在和 VS2013 中的一样。