Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.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#_.net_Winforms_Event Handling - Fatal编程技术网

C# 通用事件处理的最佳实践

C# 通用事件处理的最佳实践,c#,.net,winforms,event-handling,C#,.net,Winforms,Event Handling,在WinForms解决方案中,您有多个相同类型的控件。您需要向每个控件添加一个事件处理程序,在当前时间,事件处理程序将执行相同的操作。你不会因为任何原因期望他们之间会有差异 例如: 现在最好在如下所示的不同事件之间共享单个事件处理程序,还是使用如上所示的代码示例中的不同事件处理程序? ScheduledPatientsGrid.ProcessGridKey += ProcessGridKey; RecentPatientsGrid.ProcessGridKey += ProcessGridKey

在WinForms解决方案中,您有多个相同类型的控件。您需要向每个控件添加一个事件处理程序,在当前时间,事件处理程序将执行相同的操作。你不会因为任何原因期望他们之间会有差异

例如:

现在最好在如下所示的不同事件之间共享单个事件处理程序,还是使用如上所示的代码示例中的不同事件处理程序?

ScheduledPatientsGrid.ProcessGridKey += ProcessGridKey;
RecentPatientsGrid.ProcessGridKey += ProcessGridKey;
RecentPatientsGrid.ProcessGridKey += ProcessGridKey;                


private void ProcessGridKey(object sender, KeyEventArgs e)
{
  ...
}
在下一页中,微软似乎建议共享更好,但我注意到他们从.NET2.0(即VisualStudio2008)开始就没有更新过

在这种情况下,是否有一个指南可以提供最佳实践建议?我绝对会使用相同的方法。拥有多个功能完全相同的方法有什么可能的好处,没有一个方法的名称能说明它的功能

就我个人而言,我痛恨Visual Studio产生的
源事件名称
惯例。我更喜欢给我的事件处理程序方法起一个有意义的名字来说明它们的作用。然后,当您在设计器中向下查看事件处理程序列表时,您可以看到当单击按钮时,将发生X,而不是“将调用按钮的单击事件处理程序”,这是无用的


或者,使用lambda表达式订阅事件,并使用有意义的参数调用有意义的方法。(发送方和参数对于事件处理程序来说通常是无用的。)

我更喜欢共享,如果逻辑失控,你可以始终使用单个事件作为路由器,使用正确的方法,如

private void ProcessGridKey(object sender, KeyEventArgs e)
{
     if (sender is x)
          xmethod();
     if (sender is y)
          ymethod();    //etc 
}

我知道这种语法不太合理,因为在OP示例中,发送方始终是同一个对象,但您明白了。

在这种情况下,我通常让它们包装一个公共方法,但我会根据使用情况为它们的事件处理程序命名。这使我能够轻松地对方法进行单元测试,并(通常)减少所需的参数,堆栈跟踪中的任何错误都可以非常容易地读取进程失败的网格:

ScheduledPatientsGrid.ProcessGridKey += ScheduledPatientsGrid_ProcessGridKey;
RecentPatientsGrid.ProcessGridKey += RecentPatientsGrid_ProcessGridKey;
RecentPatientsGrid.ProcessGridKey += RecentPatientsGrid_ProcessGridKey;

... 

private void ScheduledPatientsGrid_ProcessGridKey(object sender, KeyEventArgs e)
{
   ProcessGridKey(e.Key);
}

private void RecentPatientsGrid_ProcessGridKey(object sender, KeyEventArgs e)
{
   ProcessGridKey(e.Key);
}

private void PatientsGrid_ProcessGridKey(object sender, KeyEventArgs e)
{
   ProcessGridKey(e.Key);
}

private void ProcessGridKey(Key e)
{
    ...
}

根据共享方法的功能或传入的参数,您的里程数可能会有所不同。(例如,在我上面的示例中,我重复了从
KeyEventArgs

中拉出
键的操作,这是有意义的。我从未想过设计器方面(可能是因为我从未使用过设计器>)@ChrisSinclair:如果你从未使用过设计器,那么使用那些可怜的名称的借口就更少了;)也许。我倾向于阅读事件包装,然后说“这是当用户点击按钮(或任何事件)时发生的事情”,但再想想,我想事件侦听器真的不应该关心调用它们的上下文。如果它从鼠标点击变为按键,那么我的代码的其余部分是否会在意呢?它应该在意吗?我想不是。唯一重要的地方是我首先在哪里注册活动。谢谢,下一次我给你发信息时,我会强烈地考虑这个问题。再想一想(是的,评论垃圾),它甚至在注册侦听器时也很有意义
MyButton.Click+=MyButton\u Click
绝对不会告诉我将要发生什么
MyButton.Click+=ValidateFormInput
告诉我单击按钮时将执行验证;它的实用性和可读性要大得多D
ScheduledPatientsGrid.ProcessGridKey += ScheduledPatientsGrid_ProcessGridKey;
RecentPatientsGrid.ProcessGridKey += RecentPatientsGrid_ProcessGridKey;
RecentPatientsGrid.ProcessGridKey += RecentPatientsGrid_ProcessGridKey;

... 

private void ScheduledPatientsGrid_ProcessGridKey(object sender, KeyEventArgs e)
{
   ProcessGridKey(e.Key);
}

private void RecentPatientsGrid_ProcessGridKey(object sender, KeyEventArgs e)
{
   ProcessGridKey(e.Key);
}

private void PatientsGrid_ProcessGridKey(object sender, KeyEventArgs e)
{
   ProcessGridKey(e.Key);
}

private void ProcessGridKey(Key e)
{
    ...
}