Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 更好的方法是调用空方法还是使用许多接口_C# - Fatal编程技术网

C# 更好的方法是调用空方法还是使用许多接口

C# 更好的方法是调用空方法还是使用许多接口,c#,C#,我有几个类有一个名为Tool的基类。 在表单中,我有一个工具引用,其中包含上述类的一个instance。 当窗体上发生MouseDown事件时,我调用当前工具方法,例如“CurrentTool.MethodWhenMouseDown()” 大多数工具有3种方法: MethodWhenMouseDown() MethodWhenMouseUp() MethodWhenMouseMove() 但有一两个班级正在进行: MethodWhenMouseDown() 现在哪一个更好: 1.要让工具中的

我有几个类有一个名为Tool的基类。 在表单中,我有一个工具引用,其中包含上述类的一个instance。 当窗体上发生MouseDown事件时,我调用当前工具方法,例如“CurrentTool.MethodWhenMouseDown()”

大多数工具有3种方法:

MethodWhenMouseDown()
MethodWhenMouseUp()
MethodWhenMouseMove()
但有一两个班级正在进行:

MethodWhenMouseDown()
现在哪一个更好:

1.要让工具中的所有三个方法和不需要它们的类都调用空方法

2.实现接口,例如IMouseMoveListener,该接口仅由需要在MouseMove事件发生时执行操作的类实现。这样,如果发生MouseMove事件,我们将询问:

if(CurrentTool is MouseMoveListener)
{
(CurrentTool as IMouseMoveListener).MethodWhenMouseMove();
}
其他信息:
该程序类似于Ms Paint—工具有画笔、桶(使用移动时不需要方法的工具)、线条工具等。
在我的PaintForm中,我有一个abstrac基类工具的引用,该工具存储派生类的Instance。触发事件的东西是pictureBox


您是否考虑过工具订阅的事件代码混乱

我认为最好的做法是在表单中有一个方法,该方法将在evet发生后调用,并且该方法正在调用CurrentTool的siutable方法。例如:

void MouseMoveSubscriber(object sender, MouseEventArgs e)
{
CurrentTool.MethodWhenMouseMove(e);
}
我假设每次更改CurrentTool时都订阅和取消订阅CurrentTool的方法是一种不好的做法?
我还考虑过让所有工具引用都以形式出现,事件将由每个工具订阅,而无需取消订阅。在我看来,最大的缺点是每个工具都需要检查它是否是当前工具。

你觉得怎么样?感谢您提供的帮助。

在不了解您的场景的情况下,我将使用接口和基类的组合:
基类使用空的虚拟方法实现所有接口。基类是一个纯粹方便的构造。如果工具类希望从基类继承,但不需要该方法,则不会重写它

在使用工具的代码中,您将单独使用接口。像这样,其他类可以自由地直接实现您的接口。您可以获得这样的最大灵活性,而无需任何牺牲

var mouseMoveListener = CurrentTool as IMouseMoveListener;
var mouseDownListener = CurrentTool as IMouseDownListener;
// ...

if(mouseMoveListener != null)
    mouseMoveListener.MethodWhenMouseMove();
if(mouseDownListener != null)
    mouseDownListener.MethodWhenMouseDown();

请注意:我只使用了
as
而不是
is
as
结合使用,这取决于实际情况。但在您的特定情况下(UI事件),我认为基类带有空处理程序(虚拟方法)比很多接口要好。实际上,您的所有工具都将从某个工具库继承。调用代码将更小、更简单,无需转换到接口。

性能不是问题(当用户单击时,不必要地调用空函数的开销无关紧要),因此这实际上是关于编码的简单性和代码的清晰性/复杂性/可维护性

所以我会尽量简单

我将使用空实现实现基类,因为这是干净和简单的。它需要派生类中最少的代码来获得所需的结果。这也是有道理的(如果您不重写click-upcall,那么您实际上是在说“当单击鼠标时,我不想对它做任何事情”)

下一个选项是为鼠标上/下/点击提供事件,并让派生类订阅这些事件(如果它们愿意)。使用事件是一种标准模式,但它有一个缺点,就是您必须处理糟糕的订阅和取消订阅调用。这样做的好处是,如果将它们公开,那么任何人都可以处理这些事件,而不仅仅是派生类

我会避免使用接口和强制转换——对我来说,这感觉像是一种笨拙的方法——它真正实现的只是将“空函数”方法分割成多个不同的类型,而不是一组简单的3个虚拟方法。你不需要仅仅调用这些方法并且知道它们会起作用,你必须首先进行大量的类型转换和检查——这看起来很混乱

编辑 由于您在问题中添加了更多内容,我已经阅读了它,并且想到了另一种可能性:创建一个基本工具类,该类提供所有派生类都需要重写的虚拟MouseDown处理程序。所有的普通工具都会从中派生出来

可以派生一个附加的DragTool类作为中间类,该类添加了一对特殊的拖动工具所需的MouseMove和MouseUp处理程序

i、 e


这意味着您的任何工具中都不会有空的实现。

您考虑过这些工具订阅的事件吗?不清楚为什么工具不能只订阅它想要收听的事件。恐怕我没有理解第二段。如果一个基类实现了所有这些接口,那么所有派生类也都实现了它们,因此我认为CurrentTool不可能不是IMouseMoveListener或IMouseDownListener。@user1593872:这一观察是正确的。但其他类可能决定只实现其中一个接口,而不从“
工具库”
”派生。我不同意“笨拙的方法”。他提到的接口称为“角色接口”,如果消费者支持多个角色,这就是使用它们的方式。@DanielHilgarth:接口是一种很好的方法,其中一组不相关的类需要支持一种常见的行为,但是,发明一个全新的接口只是为了避免在少数几个直接相关的类中使用虚拟方法,这是过分的。(这个问题似乎意味着更多的代码,更复杂,更难理解,效率更低。从哪方面来说,这是一个胜利?这似乎不是适用于这个特定案例的合适模式。除非这个案例比问题所暗示的更多)我同意:如果使用这些接口的唯一地方是这个表单,那么接口
ToolBase (abstract MouseDown)
  |
  +- ClickTool1
  +- ClickTool2
  +- DragToolBase (abstract MouseMove + MouseUp)
      |
      +- DragTool1
      +- DragTool2