避免重复接口的默认值

Joe*_*Fan 11 c#

有时候,我有默认参数的接口,我想从调用实现方法实现类(除了从外面它).我也想使用它的默认参数.

但是,如果我只是按名称调用方法,则不能使用默认参数,因为它们仅在接口中定义.我可以在实现方法中重复默认规范,但这是不可取的,因为DRY和所有这些都需要(特别是编译器不会检查它们实际上是否与接口的默认值匹配!)

我通过引入所谓的构件解决这个_this因为这是相同的this,除了它被声明为接口类型.然后当我想使用默认参数时,我用方法调用_this.这是示例代码:

public interface IMovable
{
    // I define the default parameters in only one place
    void Move(int direction = 90, int speed = 100);
}

public class Ball: IMovable
{
    // Here is my pattern
    private readonly IMovable _this;

    public Ball()
    {
        // Here is my pattern
        _this = this;
    }

    // I don't want to repeat the defaults from the interface here, e.g.
    // public void Move(int direction = 90, int speed = 100)
    public void Move(int direction, int speed)
    {
        // ...
    }

    public void Play()
    {
        // ...

        //This would not compile
        //Move();

        // Now I can call "Move" using its defaults
        _this.Move();

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这种模式有什么问题或以更好的方式解决问题吗?(顺便说一句,我认为这是我必须做的事情的语言缺陷)

编辑:不是为什么在接口上定义的C#4可选参数未在实现类上强制执行?......我主要是问如何解决这种语言怪癖,而不是问为什么它是这样设计的

Tim*_*lds 5

你有三个选择。

使用扩展方法作为默认值

public interface IMovable
{
    void Move(int direction, int speed);
}

public static MovableExtensions
{
    public static void Move(this IMovable movable)
    {
        movable.Move(90, 100);
    }
}
Run Code Online (Sandbox Code Playgroud)

显式实现接口

这样您就不必重复IMovable接口中定义的默认值,并且接口和实现的默认值永远不会不同步。

public class Ball : IMovable
{    
    void IMovable.Move(int direction, int speed)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

重复默认参数

public class Ball : IMovable
{    
    public void Move(int direction = 90, int speed = 100)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

您的代码可能有两个用户:一个只使用IMovable接口,一个只使用Ball类。可以说,可能存在一个模糊的场景,其中移动 an 的默认值IMovable应该与移动 a 的默认值不同Ball,并且用户都不应该关心他们没有看到的默认值。

我承认这个解释不是很令人满意。如果您想了解更多关于为什么以这种方式设计语言的信息,请阅读 Giorgi Nakeuri 在他对您的问题的评论中链接到的问题和最佳答案:为什么在接口上定义的 C# 4 可选参数不强制用于实现类?


小智 -1

因为您实现的方法与您的接口不完全相同,并且您的编译器不知道您要实现该方法。

这是你的答案。

public interface IMovable
{
    void Move(int direction = 90, int speed = 100);
}

public class Ball : IMovable
{
    // the method you want to implement from interface 
    // MUST same with interface's declaration
    public void Move(int direction = 90, int speed = 100)
    {
        // ...
    }

    public void Play()
    {
        Move();
    }
}
Run Code Online (Sandbox Code Playgroud)