在什么类委托的实例被调用?

Naw*_*waz 5 c# events delegates

考虑一下这段代码

public class A
{
     //...
     void f()
     {  
          B b = new B();
          b.SomeEvent += this.SomeMethod;
     }
     void SomeMethod() {}
 }

 public class B
 {
     //...

     public event SomeEventHandler SomeEvent;

     void h()
     {  
          if ( SomeEvent != null )
          {
               SomeEvent.invoke();
          }
     }
 }
Run Code Online (Sandbox Code Playgroud)

在这段代码中,SomeEvent.invoke()实际上是调用SomeMethod()了类A.所以在这一点上,我几乎没有问题:

  • 在什么情况下的A,SomeMethod被调用?如何B知道要调用委托的实例?CLR如何在这里工作?
  • 另外,SomeMethod是一个私有方法,那么怎么B能从类外部调用这个方法A呢?

编辑:

在阅读了前几个答案后,我发现它Delegate有一个Target属性,在该属性上调用委托.但我真的不明白这个Target属性设置的确切步骤是什么?是谁设定的?当我写作时b.SomeEvent += this.SomeMethod;,它是否也设置了Target属性?究竟怎么样?

Han*_*ant 4

 b.SomeEvent += this.SomeMethod
Run Code Online (Sandbox Code Playgroud)

这里有很多糖分,让你看不到真正发生的事情。写出来,类似于这样:

 b.SomeEvent.add(new MulticastDelegate(this, SomeMethod));     // not legal code
Run Code Online (Sandbox Code Playgroud)

其中 add() 是事件的添加访问器,当您未显式声明自己的访问器时,编译器会自动生成一个访问器。委托构造函数的第一个参数是您要询问的对象实例,即委托对象的 Target 属性。请注意,这有副作用,事件订阅保留对您的b对象的引用。这会阻止它被垃圾收集,这在调用事件时会很糟糕。

这也可能是一个问题,您可能会无意中泄漏对象引用。您的代码中没有好的方法可以取消订阅事件处理程序,因此 A 对象的生存时间与您调用 h() 的 B 对象一样长。