c# 4.0默认参数

本文关键字:参数 默认 | 更新日期: 2023-09-27 18:14:39

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

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

c# 4.0默认参数

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

因此,它们不能在实现中被'重写',因为没有什么可重写的。

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


从你的评论来看,你建议的是某种形式的"虚拟"参数(运行时类型在其中声明),CLR必须"知道"。我猜这个实现被排除是因为成本(设计,文档,实现,测试等)与它所带来的好处相比太高了(尽管这只是猜测!)。另外,还有默认的委托方法选项,例如:

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

被编译器重写为:

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

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

你的想法有缺陷。您说默认值是实现细节。接口与实现细节无关。按照这个逻辑,指定一个默认值确实不属于接口。

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

2)因为接口定义了一个操作契约。界面显示默认值必须是…因此类必须这样实现