【问题标题】:How to avoid to implement method with useless parameters to satisfy interface conditions?如何避免实现带有无用参数的方法以满足接口条件?
【发布时间】:2019-11-08 12:50:18
【问题描述】:

我有一个带有 Bar 方法的 IFoo 接口,带有一个字符串参数。这个接口有一个实现,它返回一个常量值,根本不使用参数。另一个使用参数。

如何避免这个无用的参数? 这是一个虚拟实现

  public interface IFoo
    {
        string Bar(string parameter);
    }

    public class Foo : IFoo
    {
        public string Bar(string parameter)
        {
            return string.Format("{0}Fooooooo", parameter);
        }
    }

    public class ConstantFoo : IFoo
    {
        public string Bar(string parameter)
        {
            return "Baaaaaaar";
        }
    }

    public class Caller
    {
        private readonly IFoo _foo;
        private readonly IFoo _constFoo;
        public Caller()
        {
            _foo = new Foo();
            _constFoo = new ConstantFoo();
        }
        public void DummyUsage()
        {
            string arg = "Wololo";
            Console.WriteLine(_foo.Bar(arg));
            Console.WriteLine(_constFoo.Bar(arg));

        }
    }

【问题讨论】:

  • 接口定义合约..你不是强制使用这个参数。另一种情况是例如事件。想象一下微软为您提供了一些事件。通常 eventhandler 方法有 2 个参数 void MyHandler(object sender, EventArgs e) 一旦事件被触发,这个处理程序就会被调用并且 2 个参数在方法范围内可用。你可以使用它们,但没有强迫你使用它们的力量。如果您是界面的生产者,您也可以将其应用于界面(第 3 方),也许您可​​以考虑如何更改应用程序的设计。
  • 接口是合约。当你有IFoo的实例时,你只知道它有Bar(string),你不知道参数是否无用,你必须传递它。实现不使用也没关系,但还是要遵守约定,将此参数定义为方法签名。你可以给它一些花哨的名字,例如notUsed 甚至给出可选的默认值(或使用重载),那么如果你有ConstantFoo 实例,你可以不带参数调用Bar()
  • Sinatr 评论示例:dotnetfiddle.net/I9rrkD
  • @Fildor 我认为在这种情况下可选参数不是好主意
  • @PeterM。我刚刚编译了一个 Sinatr 建议 OP 看到的示例。

标签: c# oop inheritance interface


【解决方案1】:

类实现的函数或属性的签名始终需要与相应的接口相同。 如果您自己可以控制接口,则可以更改接口和实现类中的签名。

public interface IFoo
{
    string Bar();
}

public class Foo : IFoo
{
    public string Bar()
    {
        return "Fooooooo";
    }
}

如果这不是您想要的,可能表明您的继承模型没有很好地定义。

【讨论】:

  • 你在哪里丢失parameter .. 是如何定义的?
【解决方案2】:

在接口IFoo中声明一个不带任何参数的附加方法Bar()

public interface IFoo
{
    string Bar(string parameter);

    string Bar();
}

public class Foo : IFoo
{
    public string Bar(string parameter)
    {
        return string.Format("{0}Fooooooo", parameter);
    }

    public string Bar()
    {
        return string.Empty;
    }
}

public class ConstantFoo : IFoo
{
    public string Bar(string parameter)
    {
        return string.Empty;
    }

    public string Bar()
    {
        return "Baaaaaaar";
    }
}

public class Caller
{
    private readonly IFoo _foo;
    private readonly IFoo _constFoo;
    public Caller()
    {
        _foo = new Foo();
        _constFoo = new ConstantFoo();
    }
    public void DummyUsage()
    {
        string arg = "Wololo";
        Console.WriteLine(_foo.Bar(arg));
        Console.WriteLine(_constFoo.Bar());

    }
}

【讨论】:

    【解决方案3】:

    你的例子有一个事实。你作为班级的生产者知道你确切知道什么类型的实例是IFoo

    public class Caller
        {
            private readonly IFoo _foo;
            private readonly IFoo _constFoo;
            public Caller()
            {
                _foo = new Foo();   // => here is exact instance type
                _constFoo = new ConstantFoo(); // => here is exact instance type
            }
            public void DummyUsage()
            {
                string arg = "Wololo";
                Console.WriteLine(_foo.Bar(arg)); // -> here you know that you need parameterarg
                Console.WriteLine(_constFoo.Bar(arg)); // -> here you know that you do not need parameter arg
    
            }
    

    现在想想:

    public class Caller
        {
            private readonly IEnumerable<IFoo> _fooServices;
    
            public Caller(IEnumerable<IFoo> fooServices)
            {
                _fooServices = fooServices;
            }
            public void DummyUsage()
            {
                string arg = "Wololo";
    
               foreach(IFoo fooService in _fooServices)
              {
                   Console.WriteLine(fooService.Bar(arg)); //==> you do not know what type of foo it is if it require internally argument or not .. But you have to pass it to satisfy contract defined by IFoo interface
              }
    
            }
    

    现在又一个

    假设您有 2 个接口:

    interface IFoo 
    {
        void Bar();
    }
    
    interface IParametrizedFoo
    {
        void Bar(string parameter);
    }
    

    然后你就可以实现了

    public class Foo : IParametrizedFoo
        {
            public string Bar(string parameter)
            {
                return string.Format("{0}Fooooooo", parameter);
            }
        }
    
        public class ConstantFoo : IFoo, IParametrizedFoo
        {
            public string Bar()
            {
                return "Baaaaaaar";
            }
    
          string  IParametrizedFoo.Bar(string parameter)
    {
    Bar();
    }
        }
    

    然后使用

    public class Caller
        {
            private readonly IParametrizedFoo _parametrizedFoo;
            private readonly IFoo _foo;
            public Caller(IParametrizedFoo parametrizedFoo, IFoo foo)
            {
                _parametrizedFoo= parametrizedFoo;
                _foo= foo;
            }
            public void DummyUsage()
            {
                string arg = "Wololo";
                Console.WriteLine(parametrizedFoo.Bar(arg));
                Console.WriteLine(_foo.Bar());
    
            }
    

    但我仍然认为不是最好的设计

    【讨论】:

      猜你喜欢
      • 2011-04-07
      • 1970-01-01
      • 1970-01-01
      • 2011-02-01
      • 1970-01-01
      • 2012-08-01
      • 2018-10-15
      • 1970-01-01
      • 2013-12-30
      相关资源
      最近更新 更多