与可选参数值的一致性

Are*_*ren 5 .net c# coding-style optional-parameters

我已经使用.NET 4以有限的方式使用可选参数了一段时间.我最近想过如何实现可选参数以及我遇到的事情.

请看以下示例:

public interface ITest
{
    void Go(string val = "Interface");
}
Run Code Online (Sandbox Code Playgroud)

实现这一点的唯一要求是实现最大形式的签名void Go (string val),实际上我们不需要实现可选参数,因为编译器会处理该连接(尽管使用可选参数的选项在使用时不可用)具体类直接).

有了这个说法,为了在两个地方提供功能,并且为了在实现中可以发现,可以在接口和实现中实现可选声明.事实上,生产力工具ReSharper在实现接口时会自动将此可选声明拉到具体类型.这似乎是合乎逻辑的事情.然而...

什么阻止我们在具体类型和界面中使用不同的值?这引发了我今天早上的警钟,好像有人进入更改该值,并忘记将其保留在覆盖/接口的继​​承之下,根据您访问对象的方式,行为将完全不同.调试可能非常令人沮丧.

试试这个LINQpad脚本:

void Main()
{
    IA iface = new A();
    A cls = new A();

    iface.Go();
    cls.Go();
}

interface IA
{
    void Go(string val = "Interface");
}

class A : IA
{
    public void Go(string val = "Class") { val.Dump(); }
}
Run Code Online (Sandbox Code Playgroud)

输出将是:

Interface
Class
Run Code Online (Sandbox Code Playgroud)

这让我想到了我的实际问题:

题:

什么(如果有的话?)这样,我们才能保障这一点,而不会失去使用可选的参数变体与具体类的能力,所以它的发现/读取到编码器?

以前有人遇到过这个问题吗?你是怎么解决的?是否有任何最佳实践可以帮助防止此问题在多开发人员大规模代码库中变得普遍?

D S*_*ley 3

没有什么可以阻止你这样做。使用可选参数将值烘焙到方法调用中。正如您所看到的,调用IA.Go()A.Go()为您提供不同的值,因为它们被编译为IA.Go("Interface")A.Go("Class")

解决方法(意味着在实现中仅提供“默认”参数)是使用重载不是可选参数:

interface IA
{
    void Go();
    void Go(string val);
}

public class A : IA
{
    public void Go()
    {
        Go("Class");
    }
    public void Go(string val) { val.Dump(); }
}
Run Code Online (Sandbox Code Playgroud)

其他一些选项:

  • 添加一个单元测试来检查该条件。但是,您必须为每个实现执行此操作。
  • 研究创建自定义代码分析规则

  • 您可以添加一个单元测试来检查该条件。您必须为每个实现执行此操作。您还可以研究[创建自定义代码分析规则](http://blogs.msdn.com/b/codeanalysis/archive/2010/03/26/how-to-write-custom-static-code-analysis-rules -并将它们集成到-visual-studio-2010.aspx)。 (3认同)