在接口中声明可选参数有什么意义吗?

22

在接口方法中,您可以声明可选参数,但实现类不必将参数声明为可选参数,就像Eric Lippert解释的那样。另外,在实现类中将参数声明为可选参数,但是在接口中则不能。

那么,在接口中声明可选参数是否有任何原因?如果没有,为什么允许这样做?

示例:

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) { }
}

看起来是重复的:https://dev59.com/zG445IYBdhLWcg3wUYrM - Tigran
6个回答

23

示例:

public interface IService1
{
    void MyMethod(string text, bool flag = true);
}

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

用法:

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

MyService1a的第二个参数将作为接口中的默认参数传递,并且其值为true


21
为什么这么做呢?是为了让调用者在编译时只有接口类型的情况下更容易使用。
public void Foo(IService1 service)
{
    service.MyMethod("Text"); // Calls MyMethod("Text", false)
}

对于调用者而言,仅知道某个对象实现了哪些接口是非常普遍的,而不知道具体的类型 - 因此,如果你认为可选参数是一个好主意(这是有争议的),那么在接口上和在具体类型上都具备可选参数是同样合理的。


3
如果正在设计一个带有方法Foo和参数Bar的接口,并且99%(但不是100%)的Foo调用将零参数传递给Bar,则必须执行以下操作之一:
  1. 在接口方法中包含重载,其中包括是否包含参数`Bar`,这样要求该接口的每个实现都包括额外的方法,但无需指定调用者。
  2. 仅包括包含`Bar`的方法,节省实现者的额外方法成本,但需要在每个调用站点上包含额外的参数。
  3. 在接口中将参数定义为可选,这样可以使实现者和消费者的东西更方便。

当它可行时,第3种选择似乎最方便。


1

它的好处在于接口可以按照自己想要的方式声明它们,因此在制作接口时,您可以获得所需的灵活性。换句话说,派生类中的实现者可以根据需要将参数设置为可选或必需等。如果它不是可选的,则派生类必须具有它。

您上面的示例就展示了这一点——在派生类中具有灵活性。


0

我认为你不应该这样做,因为接口不是用来处理状态而是处理功能的。类本身应该处理状态以及定义属性以及由这些类执行的操作(我认为可选参数是对状态的微妙定义)。关键在于通过调用其接口或类来声明和使用对象。例如:

public interface IFoo
{
    void Bar(int i, int j);
}

public class Foo : IFoo
{
    public void Bar(int i, int j = 0)
    {
        Console.WriteLine(i);
        Console.WriteLine(j);
    }
}

class Program
{
    static void Main(string[] args)
    {
        //referring to interface requires second arg
        IFoo foo = new Foo();
        foo.Bar(1);

        //allows one arg and uses optional arg
        Foo foo = new Foo();
        foo.Bar(1);
    }
}

本质上,功能取决于对象所封装的类型以及该类或接口对对象应用的相应要求。如果接口需要它,它也需要(因为它的功能类似于接口),如果接口不需要它,它也不需要(功能类似于接口)。但是,您必须自问接口或实现/继承对象是否结构正确,然而,接口具有默认值的灵活性并不是一条硬性规定。


0

界面设计师对默认参数的假设可能与实现者的设计不同。

默认参数只是由编译器扩展,参数被实际默认值替换。

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

当您在类实例上调用方法时,编译器将替换类上指定的默认值。


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