3

Ted Faison 在关于基于事件的软件设计的播客中提到 .NET、C++ 和 Java 事件语句中的“sender”和“self”对象,例如:

private void Button_Click(object sender, RoutedEventArgs e)

是用词不当,因为例如在上面的示例中,“发送者”实际上并不是产生事件的对象,而是代理,因为您不希望将应用程序紧密耦合。

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

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

他还提到,例如,您不应该从 EventArgs 继承,因为它会导致类爆炸式增长,每个事件一个,它只传输几个变量。在他看来,很多时候,您可以发送一个字符串。他提到,这种观点与微软模式和实践所建议的相反。

对这些领域有什么想法吗?

4

2 回答 2

1

首先-“发件人”将持有对您单击的按钮的引用。如果您有多个按钮都连接到同一个事件,这就是您如何查看您点击了哪个按钮(如果您没有在事件参数中传递某些内容来阅读此内容)。

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

于 2009-03-18T22:57:33.483 回答
1

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

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 不会foo。但这可以说是因为我们实施Foo.SomeEvent不正确。

老实说,在大多数情况下你不需要检查sender;这很有用的主要时间是当许多控件共享一个处理程序时。您通常应该能够假设发件人是您订阅的实例(出于引用相等测试的目的)。

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

也就是说 - 我之前做过非标准事件(在 MiscUtil 的 Push LINQ 中) - 但这已经是一个非常不寻常的设置,所以它并不觉得不合适。

于 2009-03-18T23:00:26.300 回答