关于c#:有没有理由在接口中声明可选参数?

Is there any reason to declare optional parameters in an interface?

您可以在接口方法中声明可选参数,但是实现类不需要声明参数为可选参数,正如EricLippert解释的那样。相反,可以在实现类中将参数声明为可选参数,但不能在接口中声明。

那么,有没有理由在接口中声明可选参数呢?如果不允许,为什么允许这样做?

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface IService1
{
    void MyMethod(string text, bool flag = false);
}

public class MyService1a : IService1
{
    public void MyMethod(string text, bool flag) {}
}

public class MyService1b : IService1
{
    public void MyMethod(string text, bool flag = true) { }
}

public interface IService2
{
    void MyMethod(string text, bool flag);
}

public class MyService2b : IService2
{
    public void MyMethod(string text, bool flag = false) { }
}


例子:

1
2
3
4
5
6
7
8
9
public interface IService1
{
    void MyMethod(string text, bool flag = true);
}

public class MyService1a : IService1
{
    public void MyMethod(string text, bool flag) { }
}

用途:

1
2
IService1 ser = new MyService1a();
ser.MyMethod("A");

传递给MyService1a的第二个参数将是true,作为接口中的默认参数。


这样做的原因是,当调用者的编译时类型只是接口时,可以更容易地使用调用者:

1
2
3
4
public void Foo(IService1 service)
{
    service.MyMethod("Text"); // Calls MyMethod("Text", false)
}

对于调用者来说,只知道某个实现的接口而不是具体的类型是很常见的——因此,如果您认为可选参数是一个好主意(这是有争议的),那么在接口上使用它们和在具体的类型上使用它们是一样有意义的。


如果设计接口的方法Foo采用参数Bar和99%(但不是100%)调用Foo的方法Bar通过零,则必须:

  • 包含在接口方法重载中,该重载不包含参数"bar",因此要求该接口的每个实现都包含一个额外的方法,但释放了需要指定该方法的调用方。
  • 只包括一个包含"bar"的方法,这样可以节省实现人员额外方法的成本,但需要在每个调用站点都包含一个额外的参数。
  • 在接口中将参数定义为可选的,从而使实现者和使用者都更方便。

    选项3在可行时对我来说似乎最方便。



    它很有用,因为接口可以按它想要的方式声明它们,所以在生成接口时,您可以获得您想要的确切的灵活性。换句话说,派生类中的实现者可以根据需要使参数成为可选的,或者使它成为必需的等等。如果它不是可选的,派生类必须具有它。

    上面的示例仅显示了这一点——派生类中的灵活性。


    接口设计器对默认参数的假设可能与实现者的设计不同。

    默认参数由编译器简单地展开,参数由实际的默认值替换。

    当您对作为接口实例的对象调用方法时,编译器将替换接口上指定的默认值。

    并且,当您对一个作为类实例的对象调用方法时,编译器将替换在类上指定的默认值。