如何从匿名定义的事件处理程序中提取“真实”目标

本文关键字:提取 真实 目标 程序 事件处理 定义 | 更新日期: 2023-09-27 18:37:03

在这里跟进我的问题:

根据评论——

编译器创建一个具有虚构名称的类成员,并附加它,就像附加声明的方法一样。

我不完全理解这意味着什么,但我可以验证,如果不是说

Foo.Bar += (S, E) => { /*Code Goes Here*/ }

我反而说

Foo.Bar += FooBar;
private void FooBar( object sender, EventArgs e ){
    /*Code Goes Here*/
}

然后Event.TargetWhatIsThis.App.<>c更改为WhatIsThis.App.

这太棒了,但我不能保证我总是会编写一个实际的方法来附加到事件处理程序。

在我确实使用匿名方法的情况下,有没有办法提取真正的目标,或者我只是被归类为使用定义的方法(我的意思是,我想我可以接受这一点,但如果有一些高科技巫术,我可以用它来提取真正的目标,那么我完全赞成)。

如何从匿名定义的事件处理程序中提取“真实”目标

不完全理解这意味着什么

让我们修复您的理解。假设您有:

class C 
{
  int x;
  void M(int y) 
  { 
    int z = GetZ(); 
    Func<int, int> f = q => q + x + y + z;
    ... 

f 是委托。它有一个接收器和一个作为接收器的方法的方法。(请注意,这实际上并不是一个严格的要求,但对于我们今天的目的来说,角落情况是模糊的。

具有该方法的接收器是什么类型

可以是C,接收器等于this吗? 不。 为什么不呢? 因为那么我们如何跟踪 y 和 z 的值呢?每次调用 M 时可能有不同的值,因此不能this接收方。

编译器所做的是生成一个新类:

class C 
{
  int x;
  class Locals
  {
    public C __this;
    public int y;
    public int z;
    public int A(int q) { return q + __this.x + y + z; }
  }
  void M(int y) 
  {
    Locals locals = new Locals();
    locals.__this = this;
    locals.y = y;
    locals.z = GetZ(); 
    Func<int, int> f = locals.A;
    ... 

那么接收者是什么?当地人的价值。方法是什么?一个。

当然,当地人和A都被赋予了疯狂的名字,所以你不能偶然地称呼他们。

在我确实使用匿名方法的情况下,有没有办法提取真正的目标

我保证,您正在提取真正的接收器。

正在开发一个扩展以使用事件处理程序执行某些操作,我需要能够辨别事件处理程序的目标是什么

请不要那样做。事件处理程序的接收器是提供处理程序的代码的实现详细信息。它不是由你做决定的。编译器在为事件处理程序生成接收器时完全有权做出他们喜欢的任何选择,他们确实这样做了。 例如,考虑如果在迭代器块或异步方法中创建事件处理程序会发生什么情况。或者,事件由某些将序列操作应用于事件的反应式扩展代码订阅。同样,编译器将到处生成类。你不能指望类是"明智的"。

您可以依赖的是:订阅者希望在发生某些事情时调用给定的方法。这是你必须遵守的合同;不要试图对订阅者进行事后猜测。