可选参数和接口 - 意外结果

时间:2013-10-21 17:23:17

标签: c# interface optional-parameters

我支持一些具有可选参数和接口的代码。

作为简化示例:界面中的默认值为2,实现类中的默认值为1.

public interface IOptionalInterface
{
    int Get(int x = 2);
}

public class ClassX : IOptionalInterface
{
    public int Get(int x = 1)
    {
        return x;
    }
}

正如我所料,这段代码通过了。

        Assert.AreEqual(new ClassX().Get(), 1);

但是,当我将类作为接口传回,并稍后调用它时,我从接口获取可选参数;这令我感到惊讶。

    private IOptionalInterface Build()
    {
        return new ClassX();
    } 

    public void Expect1()
    {
        var y = Build();
        Assert.AreEqual(y.Get(), 1);  // fails, it returns 2.
    }

我缺少哪些主要的设计考虑因素才能优先考虑?

是否有一种干净的方法可以确保实现类设置默认值?

2 个答案:

答案 0 :(得分:3)

可选参数是在调用点调用的纯编译时功能。

当您使用可选参数调用方法时,编译器将查找该参数的默认值并在调用中插入该文字值。
因此,默认值将根据调用站点的编译时类型进行解析。

答案 1 :(得分:1)

这是因为 - 像扩展方法一样 - 可选参数是编译器技巧而不是真正的语言特性。

如此恰当 - 用扩展方法解决问题:

public interface IDoSomething {
    void DoThis(int parameter);
}

public static class DoSomethingDefaults {
    public static void DoThis(this IDoSomething x) {
        x.DoSomething(123); //default value
    }
}

///
new ClassThatImplementsDoSomething().DoThis();
new ClassThatImplementsDoSomething().DoThis(456);

它并不像真正的可选参数一样超级光滑,但在大多数情况下,它们会做同样的事情并正常工作。

保持默认设置与您的界面(我甚至建议使用相同的文件),并希望您的项目的新手能够追踪正在发生的事情并不会太难。