Button_Click中的“发件人”(对象发件人......真的是发件人吗?

时间:2009-03-18 22:25:55

标签: c# event-driven-design

Ted Faison在podcast on event-based software design中提到了.NET,C ++和Java事件语句中的“发送者”和“自我”对象,例如:

private void Button_Click(object sender, RoutedEventArgs e)

是一个用词不当的例子,例如在上面的示例中,“sender”实际上并不是生成事件而是代理的对象,因为您不希望紧密地耦合应用程序。

我是否对他的理解不正确(因为当我调试它时,“发件人”确实似乎是原始对象)。

或者这些语言中的常见事件模式(例如,常见的点击处理程序)是紧密耦合的,但它们应该更加分离,例如在复合应用程序中

他也提到过,例如你不应该继承EventArgs,因为它会导致类爆炸,每个事件一个,只传输一些变量。他认为,很多时候你可以发送一个字符串。他提到这种观点与微软模式和实践所暗示的相反。

关于这些方面的任何想法?

2 个答案:

答案 0 :(得分:1)

首先 - '发件人'将保留对您点击的按钮的引用。如果你有多个按钮都挂钩到同一个事件,这就是你如何看到你点击了哪个按钮(如果你没有在事件参数中传递一些内容来阅读它)。

此外,我在某种程度上同意编写继承frmo EventArgs的新eventargs会导致类的爆炸 - 因此请使用causion。我喜欢只提高一个EventArgs.Empty然后让代码捕获事件显式查询引发数据事件的对象。我的意思是 - 一旦你抓住了这个事件,你就不会从事件参数中读取数据,而是转到引发事件的对象并读取你感兴趣的属性。这样可以更容易地阅读你需要的内容但是当然 - 您可能会发现自己处于这样一种情况,即在引发的事件和您阅读属性之间这些属性发生了变化。

答案 1 :(得分:1)

在大多数情况下,sender 引发事件的Button(或其他)。在某些情况下,不是的情况 - 例如(可能是懒惰的)pass-thru事件:

class Foo {
   private Bar bar;
   public Foo(Bar bar) {
       this.bar = bar;
   }
   public event EventHandler SomeEvent {
       add {bar.SomeEvent += value;}
       remove {bar.SomeEvent -= value;}
   }
   //...
}

在这里,如果我们订阅了foo.SomeEvent,我们实际上会收回由Bar实例发起的事件 - 因此sender 不会为{{1 }}。但这可以说是因为我们错误地实施了foo

说实话,在大多数情况下,您无需检查Foo.SomeEvent;这个有用的主要时间是许多控件共享一个处理程序。您通常应该能够假定发件人是您订阅的实例(出于参考 - 相等性测试的目的)。

重新sender - 标准模式(创建新事件类型时)建议您继承此内容。我不建议偏离这一点。一个小原因是它允许您使用EventArgs,但也有其他差异原因。此外 - 有时做其他人所期望的是足够的理由;人们期望 EventHandler<T>派生的价值。

那就是说 - 我之前已经完成了非标准事件(在MiscUtil的推送LINQ中) - 但这已经是一个非常不寻常的设置,所以它感觉不合适。