C# 4.0 默认参数

3

Consider the following console application:

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)为什么在接口中没有一种不提供值就可以将参数指定为可选的方法。 我认为默认值是实现细节。如果我们用传统的非可选参数方式编写此代码,我们将在接口中创建两个重载,并且默认值将在实现类中指定。也就是说,我们将有:

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)为什么我们不能在实现类中重写默认值!

2个回答

4
在.Net中,缺省值实际上是基于编译器的语法糖。在调用时,编译器为您添加了默认值。由于编译时无法知道对象的运行时类型,因此必须插入接口中定义的值。
因此,在实现中它们不能被“覆盖”,因为没有东西可以被覆盖。
Eric Lippert在有关可选参数的主题上写了一系列非常有趣的博客文章,第一篇可以在这里找到。 更新
根据您的评论,您建议的是某种形式的“虚拟”参数(即运行时类型声明),CLR必须“知道”。我猜想这个实现被排除在外,因为它带来的成本(设计、文档、实现、测试等)与它所带来的好处相比太高了(尽管这只是一个猜测!)。 或者,还有默认委托方法选项,即:
void M(bool y = false) { ... whatever ... }

编译器将其重写为:

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

但是如果选择这种方法,一旦考虑到多个可选参数和命名参数,就会导致过载的水平可能达到不可接受的程度。

谢谢Rich,我看到问题了。他们添加一个“可选”关键字而不是在接口上提供一个值会更有意义吧?对我来说,在接口上设置默认值没有任何意义。 - magritte

3

1) 你的想法有缺陷。你说默认值是一种实现细节,但接口不应包含实现细节。按照这个逻辑,指定默认值真的不应该出现在接口中。

只需使用重载方法编写接口即可。这样不仅定义更清晰,而且在与其他语言进行接口时,接口也更兼容,并且不会出现可选参数带来的版本问题。

2) 因为接口定义了操作契约。接口规定了默认值必须是某个值...因此类必须按照这种方式实现它。


确实,我同意,但是如果你省略它,编译器会发出警告,因为它不知道该参数是可选的。这引出了我的问题:为什么不能在不提供值的情况下将其指定为可选? - magritte
@Tony Leeper - 我还从Eric Lippert的Twitter上得到了这个好的角落案例系列:http://blogs.msdn.com/b/ericlippert/archive/2011/05/09/optional-argument-corner-cases-part-one.aspx - Justin Niessner

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