【问题标题】:C# 4.0 Default ParametersC# 4.0 默认参数
【发布时间】:2011-12-28 19:38:48
【问题描述】:

考虑以下控制台应用程序:

class Program
{
    static void Main()
    {
        MyInterface test = new MyClass();
        test.MyMethod();

        Console.ReadKey();
    }
}

interface MyInterface
{
    void MyMethod(string myString = "I am the default value on the interface");
}

class MyClass : MyInterface
{
    public void MyMethod(string myString = "I am the default value set on the implementing class")
    {
        Console.WriteLine(myString);
    }
}

这个程序的输出是:

I am the default value on the interface

(1) 为什么没有办法在接口上将参数指定为可选而不提供值。我认为默认值是实现细节。如果我们以预选参数样式编写此代码,我们将在接口中创建两个重载,并在实现类中指定默认值。 IE。我们会:

interface MyInterface
{
    void MyMethod();

    void MyMethod(string myString);
}

class MyClass : MyInterface
{
    public void MyMethod()
    {
        MyMethod("I am the default value set on the implementing class");
    }

    public void MyMethod(string myString)
    {
        Console.WriteLine(myString);
    }
}

我们期望的输出,

I am the default value set on the implementing class

(2) 为什么我们不能覆盖实现类中的默认值!

【问题讨论】:

    标签: c# c#-4.0


    【解决方案1】:

    .Net 中的默认值实际上是基于编译器的语法糖。在调用站点,编译器会为您添加默认值。它在编译时无法知道对象的运行时类型,因此它必须插入接口中定义的值。

    因此,它们不能在实现中被“覆盖”,因为没有什么可覆盖的。

    Eric Lippert 写了一系列非常有趣的关于可选参数主题的博文,其中第一篇可以在 here 找到。

    更新
    从您的 cmets 来看,您所建议的要么是某种形式的“虚拟”参数(在其中声明运行时类型),CLR 必须“知道”。我猜这个实现被排除了,因为与它带来的好处相比,成本(设计、记录、实施、测试等)太高了(尽管这只是一个猜测!)。 或者,还有默认的委托方法选项,即:

    void M(bool y = false) { ... whatever ... }
    

    被编译器重写为:

    void M() { M(false); }
    void M(bool y) { ... whatever ... }
    

    但是,一旦考虑到多个可选参数和命名参数,沿着这条路线走下去会导致潜在的不可接受的重载水平。

    【讨论】:

    • 干杯丰富,我看到了问题。添加一个“可选”关键字而不是在接口处提供一个值对他们来说不是更有意义吗?必须在界面上设置默认值对我来说毫无意义。
    【解决方案2】:

    1) 你的想法有问题。你说默认值是一个实现细节。接口没有实现细节。按照这种逻辑,指定默认值确实不属于接口。

    只需使用重载方法编写接口即可。不仅定义会更清晰,而且接口在与其他语言交互时会更加兼容,并且您不会遇到可选参数带来的版本问题。

    2) 因为接口定义了一个操作契约。接口说默认必须是某种东西......因此类必须以这种方式实现它。

    【讨论】:

    • (1) 确实,我同意,但是如果您忽略它,您将收到编译器警告,因为它不知道该参数是可选的。这就引出了我的问题(1)为什么不能在不提供值的情况下将其指定为可选?
    • @Tony Leeper - 还通过 Twitter 从 Eric Lippert 那里获得了这个优秀的系列角落案例:blogs.msdn.com/b/ericlippert/archive/2011/05/09/…
    猜你喜欢
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 2011-05-26
    • 2012-05-04
    • 2012-05-06
    • 2015-05-09
    • 2012-02-29
    相关资源
    最近更新 更多