有时候,我有默认参数的接口,我想从调用实现方法中实现类(除了从外面它).我也想使用它的默认参数.
但是,如果我只是按名称调用方法,则不能使用默认参数,因为它们仅在接口中定义.我可以在实现方法中重复默认规范,但这是不可取的,因为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可选参数未在实现类上强制执行?......我主要是问如何解决这种语言怪癖,而不是问为什么它是这样设计的
你有三个选择。
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)