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

Ric*_*chK 35 c# generics event-handling

我讨厌EventHandler.sender如果我想用它做什么,我讨厌我必须施展.我讨厌我必须创建一个继承EventArgs使用的新类EventHandler<T>.

我总是被告知这EventHandler是传统和啰嗦,等等......无论如何.但我找不到这个教条仍然存在的原因.

有一个原因,为什么建立一个新的代表是一个坏主意:

delegate void EventHandler<TSender, T>(TSender sender, T args);
Run Code Online (Sandbox Code Playgroud)

这样sender将是类型安全的,我可以传递我想要的任何东西作为参数(如果我愿意,包括自定义EventArgs).

Gre*_*ech 25

实际上有一个很好的理由要求第二个参数派生自EventArgs你的完全可信代码是否将第三方代码托管为部分信任.

因为对事件处理委托的回调是在引发代码而不是第三方代码的上下文中完成的,所以恶意第三方代码可能会将特权系统操作添加为事件处理程序,从而可能执行升级通过在完全受信任的上下文中运行代码来进行权限攻击,以使其部分受信任的上下文无法运行.

例如,如果您将处理程序声明为类型,int -> void则第三方代码可能会排队YourEvent += Enviroment.Exit(-1)并让您无意中退出该进程.这显然会导致一个易于检测的问题,但是有更多的恶意API可以排队做其他事情.

当签名(object, EventArgs) -> void存在时,框架中没有可以入队的特权操作,因为它们都不与此签名兼容.这是框架中安全代码审查的一部分,以确保这一点(遗憾的是我找不到我读到这个的源头).

因此,在某些情况下,为什么要使用标准模式存在有效的安全问题.如果您100%确定您的代码永远不会在这些情况下使用,那么事件签名指南并不重要(除了其他开发人员认为WTF之外),但如果可能那么您应该遵循它.

  • 我不明白一件事.使用`EventHandler`你不能做`YourEvent + = EnvironmentExit`,但是`YourEvent + =(sender,args)=> Environment.Exit(-1)`怎么样?是不是一样,`Exit`将在完全可信的上下文中调用? (13认同)
  • 我想问同样的问题)我们可以简单地将Enviroment.Exit(-1)包装到MyEventHandler .. (4认同)
  • @prostynick评论是否会使此回复无效?我们是否回到原点 - 除了惯例之外没有其他好理由? (4认同)
  • 这是错误的...正如@prostynick所说,你可以注册任何回调.为什么会有这么多的赞成? (3认同)
  • +1哇.好贴.这是让我回到SO的帖子类型. (2认同)

Pre*_*gha 9

除了接受的.net约定之外,没有理由使用它,任何阅读代码的人都应该很容易理解它.对此,这是一个很好的理由.

然而,这是你的代码,你可以决定什么是最适合你的.当然,当您与fcl交互时,您将不得不使用事件处理程序.

  • 话虽这么说,一个强类型的代表也将被认可:) (6认同)

Eam*_*nne 6

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