【问题标题】:Is there any reason to declare optional parameters in an interface?是否有任何理由在接口中声明可选参数?
【发布时间】:2011-10-08 19:51:34
【问题描述】:

您可以在接口方法中声明可选参数,但实现类不需要将参数声明为可选参数,如Eric Lippert explained。相反,您可以在实现类中将参数声明为可选,但不能在接口中声明。

那么有什么理由在接口中声明可选参数吗?如果不是,为什么允许?

例子:

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

【问题讨论】:

标签: c# c#-4.0 optional-parameters


【解决方案1】:

例子:

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,作为接口中的默认参数。

【讨论】:

    【解决方案2】:

    这样做的原因是为了让调用者在他们拥有的编译时类型只是接口时更容易使用:

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

    调用者只知道某个实现的接口而不知道具体类型是很常见的 - 所以 if 你认为可选参数是一个好主意(这是有争议的)将它们放在接口上就像在具体类型上一样。

    【讨论】:

      【解决方案3】:

      如果设计一个接口,其方法Foo 采用参数Bar,并且99%(但不是100%)对Foo 的调用为Bar 传递零,则必须:

      1. 在包含和不包含参数“Bar”的接口方法重载中包含,因此要求该接口的每个实现都包含一个额外的方法,但调用者无需指定它。
      2. 只包含一个包含“Bar”的方法,为实现者节省了额外方法的成本,但需要在每个调用站点都包含一个额外的参数。
      3. 在接口中将参数定义为可选,从而使实现者和消费者都更方便。

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

      【讨论】:

        【解决方案4】:

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

        您上面的示例就说明了这一点——派生类的灵活性。

        【讨论】:

          【解决方案5】:

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

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

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

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

          【讨论】:

            【解决方案6】:

            我认为您不应该这样做,主要是因为接口不是用来处理状态问题,而是处理功能问题。类本身应该处理状态和定义属性以及这些类所做的事情(我认为可选参数是状态的微妙定义)。关键在于通过诉诸接口或类来声明和使用对象。示例:

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

            本质上,功能依赖于封装对象的类型以及应用于对象的类或接口的相应要求。如果接口需要,它也需要(因为它的功能类似于接口),如果接口不需要它,它也不需要它(功能类似于接口)。尽管接口或实现/继承对象的结构是否正确,但您必须问自己,但同样,为接口设置默认值的灵活性并不是一个硬性规定。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-03-10
              • 1970-01-01
              • 2010-09-20
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多