可选参数和方法重载

3

我遇到了一个带有三个参数的库方法,所有参数都有默认值:

virtual M(bool b1 = false, string s1 = null, bool b2 = true)

方法M不应该有参数s1,所以我想将其删除,但我不希望在DLL中做出破坏性改变。客户端可以显然地忽略s1,但我不想让它留在那里,因为M可以被覆盖而参数s1是具有误导性的。所以这是我的尝试:

virtual M(bool b1 = false, bool b2 = true)
[Obsolete] virtual M(bool b1, string s1, bool b2 = true)

我认为由于可选参数编译进调用站点,现有客户端将继续使用三个参数调用该方法,而不使用 s1 的新客户端或重新编译的客户端将链接到具有两个参数的方法。 M 的每次调用都能成功解析,除了这个:
M(b2: false);

编译器报告调用"M(bool, bool)"和"M(bool, string, bool)"之间存在歧义。
奇怪的是,在拥有三个参数的方法中,参数信息(Ctrl + Shift + Space)仍然显示默认值(尽管清除并重建、重启VS、卸载和重新加载项目)。
显然,我可以通过给新的"M"起一个不同的名称来解决这个问题,但我好奇为什么它没有链接。 它应该链接吗(而过时的参数信息只是表明某些步骤已过期),还是编译器确实存在问题?
编辑:
像 @p.s.w.g 和 @JonSkeet 建议的那样,我无法在新代码中重现此问题,所以问题变成了:除了重建、重启、重新加载以强制VS重新链接外,是否还有其他什么我可以尝试?

2
我无法仅使用您第二个片段中的方法来重现此问题。对我来说,它可以编译得很好。但是,如果可以的话,我建议更改名称。通常更容易向客户传达“方法M已过时,请现在使用N”,而不是“使用仅接受两个布尔值的M的重载”。 - p.s.w.g
4
@Jon:新案例中的第二种方法有两个必需参数,但没有被指定。 - Jon Skeet
1
是的,听起来好像不同步。你能用“新鲜”的代码重现这个问题吗? - Jon Skeet
@Jon:我认为它不应该是模棱两可的原因是,过时方法中的参数不再是可选的,因此如果不提供b1和s1,编译器将不得不链接到具有两个参数的新方法。 - Giles
1
你是直接引用 DLL 而不是项目链接吗? - Bob Vale
显示剩余5条评论
1个回答

1
这有点尴尬,但也很有趣(好吧,也许更尴尬一些)。
编译器是正确的(几乎总是如此!)。我假设编译器错误是指我在问题中概述的两个M方法,但出现错误的客户端代码还覆盖了原始的带三个参数的M方法,并且仍然提供所有三个参数的默认值
当我添加了[Obsolete]后(对不起,我只是为了说明才发布它,没有想到会有关联),我才发现“第三个M”,并收到一个关于重写过时方法的警告。
我认为这可能支持@p.s.w.g的评论!

1
在改变哪些参数是可选的同时覆盖一个方法真的很令人困惑,而这似乎就是你的情况所发生的(因为虚拟基础方法已经改变)。另一件令人困惑的事情是,如果重写重命名了参数,最糟糕的情况是在重写中将 b1 重命名为 b2 - Jeppe Stig Nielsen
@JeppeStigNielsen:我同意你的看法。我认为通过删除不需要的额外参数来保持接口的清晰可能是一个不错的方法,但事实上它也是虚拟的,这使得它太令人困惑了。我正在寻找另一种解决方案! - Giles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接