【问题标题】:Check which object call to event method检查哪个对象调用了事件方法
【发布时间】:2014-09-05 16:19:27
【问题描述】:

我有组合框,每个组合框都有其 SelectedIndexChanged 事件。 我不想编写每个 ComboBox 的事件,但我想编写一个事件方法来检查哪个 ComboBox 调用事件并让控件为每个 Combobox 执行特定方法。 我已经搜索并这样写了:

private void eventmethod(object sender, EventArgs s)
{
    ComboBox cb = sender as ComboBox;
    if (cb != null & cb.Name.Equals("combobox1"))
    {
        method1();
    }
    else if (cb != null & cb.Name.Equals("combobox2"))
    {
        method2();
    }
}

有没有更有效的检查方法?

【问题讨论】:

  • 可能是if (sender == combobox1)?
  • 如果cbnull,您可以立即return
  • 如果组合框之间发生的情况有很大不同,那么您真的应该有单独的事件处理程序。
  • 如果两个控件需要做完全不同的事情,为什么要为这两个控件分配一个处理程序?
  • @Servy 我认为我很容易在一个事件处理程序中查看每个组合框。

标签: c# winforms


【解决方案1】:

这种方法破坏了Single Responsibility Principle (SRP),除非每个ComboBox.SelectedIndexChanged Event 都这样做。

最好为每个控件设置一个事件处理程序,以便可以轻松区分特定行为。如果给每个ComboBox一个特定的行为,并且它们也有一个共同的行为,那么使用辅助方法来执行共同的任务。

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
    doesCommonTasksToBePerformedThroughAHelperMethod();
}

private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) {
    // Does specific tasks
    doesCommonTasksToBePerformedThroughAHelperMethod();
}

private void doesCommonTasksToBePerformedThroughAHelperMethod() {
    // Perform common tasks
}

这是首选做法。

否则,请检查控件本身。

var cb = sender as ComboBox;

if (cb == null) return;

switch(cb) {
    case cb.Equals(comboBox1): 
        // Do something
        break;
    case cb.Equals(comboBox2):
        // Do something
        break;
}

switch 语句很少是好事。以下是有关该主题的一些链接。

  1. How to explain why a developer should avoid case statements and create some new classes?
  2. Refactoring a Switch statement
  3. Switch Statements

【讨论】:

  • 我完全同意我打破了 SRP 并且编写单独的事件处理程序是更有效的方法。 :D
【解决方案2】:

更好的做法是为每个控件设置单独的事件处理程序,然后让它们在执行相同操作时调用相同的方法:

void combo1_OnChange(object sender, EventArgs e)
{
    CommonMethod();
}
void combo2_OnChange(object sender, EventArgs e)
{
    CommonMethod();
}

在您的情况下,它们不会做同样的事情,因此拥有单独的处理程序更有意义:

void combo1_OnChange(object sender, EventArgs e)
{
    Method1();
}
void combo2_OnChange(object sender, EventArgs e)
{
    Method2();
}

如果您正在动态创建控件,则此规则的一个例外情况是,但即便如此,您也可能会使用委托。

【讨论】:

  • 为控件设置单独的事件处理程序是没有意义,这些控件在触发相同事件时都应该执行相同的操作。当控件应该做完全不同的事情时,拥有单独的处理程序当然是有意义的。
  • @Servy:我不同意。在发布代码很久之后,我经常遇到特定控件的事件必须更改的情况。我想那时我可以添加一个新事件,但是找到该控件的事件并修改它要容易得多,而不必担心我会破坏其他东西。
  • 如果您需要在为控件触发事件时调用不同的方法,则附加一个不同的方法作为该事件的处理程序。这没有比创建一个额外的包装方法更难,对不相关的代码也没有任何更显着的影响。这只是用绒毛填充代码,使找到有意义的内容变得更加困难。
  • +1 最好有单独的方法并调用一个辅助方法来执行常见任务,因为它很明显它什么都不做。
  • @WillMarcouiller 它增加了什么可能价值?将与处理程序相同的方法分配给多个控件,如何让这些控件的事件都调用相同的方法变得不那么明显?这使得它不那么显而易见。当您有专门为每个控件附加不同处理程序的代码时,它专门向代码的读者发送一条消息,说明控件为该事件执行不同的操作。它让读者更加困惑
【解决方案3】:

不需要多次检查null,只要做一次,找到就返回。也无需检查名称,因为您只需检查控件即组合框。由于您正在调用不同的方法,因此让多个控件指向此事件并没有什么坏处。我也会用 try catch 语句包围它。

private void eventmethod(object sender, EventArgs s)
{
    ComboBox cb = sender as ComboBox;
    //check for null once and return if found
    if(cb == null) return;
    //no need to call for the name just check for the combobox
    //assuming the name of the control is combobox1 and combobox2
    if (cb.Equals(combobox1))
    {
        method1();
    }
    else if (cb.Equals(combobox2))
    {
        method2();
    }
}

【讨论】:

    【解决方案4】:

    你可以使用 switch 语句:

    private void eventmethod(object sender, EventArgs s)
    {
        ComboBox cb = sender as ComboBox;
        if (cb == null) return;
        switch (cb.Name)
        {
            case "combobox1":
                method1();
                break;
            case "combobox2":
                method2();
                break;
        }
    }
    

    这不一定是最好的方法,但它确实消除了对多个空值检查的需要。

    【讨论】:

      猜你喜欢
      • 2020-05-30
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多