简体   繁体   English

为什么*应该*我们使用EventHandler

[英]Why *should* we use EventHandler

I hate EventHandler. 我讨厌EventHandler。 I hate that I have to cast the sender if I want to do anything with it. 我讨厌如果我想对sender做任何事情,就必须抛弃sender I hate that I have to make a new class inheriting from EventArgs to use EventHandler<T> . 我讨厌必须创建一个继承自EventArgs的新类才能使用EventHandler<T>

I've always been told that EventHandler is the tradition and blah, blah...whatever. 一直有人告诉我EventHandler是一种传统,等等……等等。 But I can't find a reason why this dogma is still around. 但是我找不到这个教条仍然存在的原因。

Is there a reason why it would be a bad idea to make a new delegate: 有一个原因为什么要创建一个新的代表是一个坏主意:

delegate void EventHandler<TSender, T>(TSender sender, T args);

That way the sender will be typesafe and I can pass whatever the heck I want as the arguments (including custom EventArgs if I so desire). 这样, sender将是类型安全的,并且我可以将我想要的任何内容作为参数传递(如果需要,可以包括自定义EventArgs)。

There actually is a good reason for requiring the second argument to derive from EventArgs if your fully-trusted code hosts third-party code as partially-trusted. 如果您完全信任的代码将第三方代码托管为部分信任,则实际上有充分的理由要求第二个参数从EventArgs派生。

Because the callback to the event handling delegate is done in the context of the raising code and not the third party code, it is possible for malicious third-party code to add a privileged system operation as an event handler and thus potentially execute an escalation of privilege attack by running code in your fully-trusted context that their partially-trusted context could not run. 由于事件处理委托的回调是在引发代码而不是第三方代码的上下文中完成的,因此恶意第三方代码有可能将特权系统操作添加为事件处理程序,从而有可能执行升级通过在完全受信任的上下文中运行代码来进行特权攻击,以使其部分受信任的上下文无法运行。

For example, if you declare a handler as type int -> void then the third-party code could enqueue YourEvent += Enviroment.Exit(-1) and have you exit the process unintentionally. 例如,如果您将处理程序声明为YourEvent += Enviroment.Exit(-1) int -> void类型,则第三方代码可能使YourEvent += Enviroment.Exit(-1)排队,并让您无意退出该过程。 This would obviously cause an easy-to-detect problem, but there are far more malicious APIs that could be enqueued to do other things. 这显然会引起一个易于检测的问题,但是可能有更多的恶意API可能被排入队列以执行其他操作。

When the signature is (object, EventArgs) -> void then there are no privileged operations in the framework that can be enqueued because none of them are compatible with this signature. 当签名为(object, EventArgs) -> void则框架中没有可排队的特权操作,因为它们均不与此签名兼容。 It's part of the security code review in the framework to ensure this (unfortunately I cannot find the source where I read this). 它是框架中安全代码检查的一部分,以确保做到这一点(不幸的是,我在阅读本文时无法找到源文件)。

So in certain circumstances there are valid security concerns as to why you should use the standard pattern. 因此,在某些情况下,对于为什么应使用标准模式存在有效的安全问题。 If you're 100% sure your code will never be used in these circumstances then the event signature guideline isn't as important (apart from other developers thinking WTF), but if it might be then you should follow it. 如果您100%确信在这种情况下将永远不会使用您的代码,那么事件签名指南就不那么重要了(除了其他开发人员认为WTF的情况除外),但是如果可以,那么您应该遵循它。

There is no reason to use it other than its the accepted .net convention and anyone reading your code should understand it fairly easily. 除了已接受的.net约定外 ,没有其他理由使用它,任何阅读您的代码的人都应该很容易理解它。 For this it's a good reason. 为此,这是一个很好的理由。

However it's your code and you can decide what best for you. 但是,这是您的代码,您可以决定最适合您的代码。 Of course as you interact with the fcl you will have to do it their way using event handlers. 当然,当您与fcl进行交互时,您将必须使用事件处理程序来做到这一点。

我通常将Action<...>类型用作事件处理程序-如果您不需要与特别需要EventHandler其他代码(或设计器)进行互操作,则没有理由使用它。

Well, doing all that casting is unusual, the client code quite often already knows who the sender is because it explicitly subscribed the event for only one object. 好吧,执行所有此类转换是不寻常的,客户端代码通常已经知道发送方是谁,因为它仅为一个对象明确预订了该事件。 Sharing event handlers is fairly rare. 共享事件处理程序非常少见。 If common behavior is desirable then the better approach is to derive from the class and override the OnXxxx method. 如果需要常见的行为,那么更好的方法是从类派生并重写OnXxxx方法。 You then no longer care about sender , you got this . 然后,您可以不再计较发件人 ,你得到这个

But, solve your problem trivially by including a type-safe reference to the sender in your custom EventArgs derived class. 但是,通过在自定义EventArgs派生类中包含对发件人的类型安全的引用,可以轻松解决问题。

I agree with you, the convention is stupid and/or antiquated. 我同意您的看法,惯例是愚蠢和/或过时的。 Do it the right way, with proper type safety and generics. 用正确的类型安全性和泛型以正确的方式进行操作。

It comes up all the time that you have a task to do, and you can follow the way the last guy did it OR do it another way that you think is probably better. 它总是在您有任务要做的时候出现,您可以按照最后一个人做的方式来做,也可以按照您认为可能更好的另一种方式来做。

The first choice is usually chosen -- do it the same as the last guy, and you won't get in trouble. 通常选择第一个选择-与最后一个选择相同,这样就不会遇到麻烦。 But the second choice is what improves software over the long haul. 但是第二选择是从长远角度改进软件。 (Or at least it CAN improve it, if you're right that your way is better! :) ) (或者至少可以改善它,如果您是对的,您的方法会更好!:))

As Preet Sangha said, the reason why creating such a delegate would be a bad idea is that other developers could be confused why you doing it in that way. 正如Preet Sangha所说的那样,创建这样的委托不是一个好主意,这是因为其他开发人员可能会困惑您为什么要这样做。

Using EventHandler delegate is a guideline presented here: http://msdn.microsoft.com/en-us/library/ms229011.aspx 使用EventHandler委托是此处提供的指南: http : //msdn.microsoft.com/zh-cn/library/ms229011.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM