希望:使用默认参数隐藏已弃用的方法和另一个重载

时间:2016-05-05 03:58:02

标签: c# c#-4.0 overloading optional-parameters overload-resolution

请耐心等待,这不是(相当!)任何这些答案的重复:

当试图“影响”编译器将根据可选参数引起的冲突选择的重载时,上述帖子中的答案引用C# Programming Guide,这表示此处的重载解析(OR)启发式:

  

如果两个候选人被判断为同样好,则优先选择没有可选参数的候选人,其中参数在呼叫中被省略。

足够公平。我的问题是,为什么不(或为什么不能)过时的属性(或其他一些标记)影响判断两个候选人同样好的OR决定?例如,请考虑以下重载:

[Obsolete(“This method is deprecated.”)]
[EditorBrowsable(EditorBrowsableState.Never)]]
bool foo() { return true; }

bool foo(bool optional = false) { return optional; }

似乎OR不应该判断这些重载同样好 - 带有可选参数的非弃用重载应该获胜。如果在这个过度简化的示例中就是这种情况,那么之前为foo()编译的代码将向后兼容,并且很高兴继续返回true。为这个库编译的未来代码也可以调用foo(),但是已解决的重载将返回false。

这是语言中缺少的有价值/可能的功能吗?或者还有其他方法可以实现我的工作愿望吗?感谢您的任何见解,

-Mike

3 个答案:

答案 0 :(得分:1)

过载分辨率是一个非常棘手的事情,语言设计师会长时间地考虑规则应该是什么。您添加的更多不同的考虑因素和特殊情况,可能的语言用户会遇到模糊不清的问题,因为它并没有按照他们期望的方式运作。我不相信在重载决策中添加这个新条件对语言来说是一个有价值的补充。

如果OR确实更喜欢没有ObsoluteAttribute的方法,那么在没有反射的情况下调用过时方法的唯一方法就是这样:

((Action)obj.foo)(); 

如果这是一个通用方法,则无法使用匿名类型参数调用它。这绝对是令人惊讶的行为(至少对我而言)。

ObsoleteAttribute(使用IsError = false声明)是一种为您的消费者提供更新代码的提示,而无需完全删除以前的功能。通常,如果您计划在将来的版本中删除该功能,则需要执行此操作。如果您想禁止他们完全调用此方法,您可以:

  1. 使用IsError = true设置[Obsolete("This method is deprecated.", true)],以便在重新编译代码时生成错误而不是警告。它仍然可以通过反射调用。
  2. 完全删除已弃用的功能。它不能通过反射来调用。

答案 1 :(得分:0)

总而言之这样的代码......

[Obsolete(“This method is deprecated.”)]
bool foo() { return true; }

bool foo(bool optional = false) { return optional; }

臭。当您调用foo()时,编译器将应用算法来选择正确的方法,但任何查看代码的开发人员都需要知道(并应用)该算法以了解代码的作用,因此代码的可维护性将降低很多。

在这种情况下,只需删除可选项,因为它比其他任何东西都要伤害。

答案 2 :(得分:0)

这是一个有趣的问题。不过,由于以下原因,我更喜欢它:

<强>简单

OR取决于编译到模块的方法签名,并且直观。根据任何属性将依赖范围更改为更广泛的“事物”并开始滚雪球 - 如果您考虑可能是另一个属性?或者参数的属性等。

变更管理

方法签名&amp; OR与弃用标记属性不同。后者是元数据,如果它从一个点开始影响OR,那么它可能会破坏许多现有的应用程序。特别是折旧周期较长的图书馆。

如果功能测试的代码在软判决之后开始表现不同,我会非常恼火,因为某段代码将在“未确定的未来”中逐步淘汰。