为什么通用的EventHandler<TArgs>使用如此之少?

12

.NET 2.0增加了EventHandler<TArgs>泛型委托类型,以简化编写自定义事件的过程;不需要定义一个EventArgs类及其对应的委托(例如MyEventArgsMyEventHandler),只需编写args类即可。

有鉴于此,为什么这个委托类型在.NET Framework中几乎不见踪影呢?我知道大多数核心API是在引入泛型之前开发的,但即使是像WPF这样的新框架部分,他们也选择了显式定义委托类型,例如RoutedEventHandler而不是EventHandler<RoutedEventArgs>

泛型事件处理程序委托是否存在某些固有问题?我经常使用它,担心我的代码与内置类相比显得非常不协调。


我怀疑引入EventHandler<T>只是时机不佳。当它被引入时,另一种模式(显式命名的委托)已经得到了确认,并且开始向通用委托类型的转变可能会被视为制造更大混乱的行为(因为会导致困惑的程序员问:“那个委托叫什么来着?FooEventHandler还是EventHandler<Foo>?”)。这让我很好奇,是否向IEvent<T>(由F#和Rx框架引入)的转变会奏效。 - stakx - no longer contributing
3
WPF的开发始于2003年7月,比泛型可用要早得多。当然,Windows Forms也是如此。 - Hans Passant
4个回答

7

这只是历史的偶然。如果.NET 1中有泛型,大部分其他委托将不存在。


5
我认为这没什么问题。在一些框架的地方确实会用到它,比如GeoCoordinateWatcher.Position事件中,这只是一个随机的例子。
在代码中看起来有点笨拙,不像RoutedEventHandler这样的特定类型名称 - 由于你将在WPF/Silverlight中经常使用RoutedEventHandler,可能这就是微软决定给它自己的类型的原因。

2

可能是因为编写框架级代码时,您更倾向于表达得更加明确。但当您编写工具包和应用程序级别的代码时,则不需要那么明确。


1
以下仅为个人观点,但在我看来似乎(显然)是合理的; 如果我们仔细研究一下你使用 .net 和 v studio 的工作方式,会发现泛型类型符号似乎有些“不美观”。
List<string> lst = new List<string>();
lst.Add("hello world");

虽然上面的代码非常简单、直接并且受到智能感知的良好支持,但是 EventHandler 的“外观”似乎不是很清晰。默认的智能支持只会建议使用 EventHandler,而不是它的泛型版本。此外,这种表示法看起来非常糟糕:

private event EventHandler<MyClass> SomeEvent;
private event EventHandler<AnotehrClass> OtherEvent;
privete event EventHandler<MoreClass> MoreEvents;



在查看代码时,您会每次读到“EventHandler”,因为您习惯通过名称来识别类型之间的关系。

另一方面,也可能有一个不那么难以理解、更加技术化/逻辑化的解释:
首先,在处理方法中始终会得到一个发送者对象。虽然这乍一看似乎很有用,但实际上几乎从未使用过。
此外,您的参数必须派生自EventArgs,这可能很烦人,有时甚至由于使用现有组件而变得不可能。
除了典型的泛型(例如IList/List)之外,您还可以使用更抽象的类型(如接口)或简单类型(如double)。
最后,微软引入了那些符号规则/建议——对于您关于路由事件的示例,规则可能是它的类型被标记为路由事件,因为其名称以“Routed”开头。而事件本身的命名则以“Preview”开头。

正如我所提到的:这只是我的观点,请不要责怪我;)


sender 参数绝对有其用途。每当您将相同的处理程序绑定到多个对象上时,它就会发挥作用。虽然它并不总是有用,但使用您的代码的人们希望它可用。至于使用 EventArgs 的派生类,我个人认为这促进了在您的代码和用户之间放置门的想法-确保您永远不会意外地给他们一个您不希望他们修改的可变对象等。不过,您关于命名的评论绝对是有效的。让我希望 C# 有 typedef... - Bradley Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接