考虑这段代码,
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();
}
}
}
在此代码片段中,SomeEvent.invoke()
实际上调用了 A
类的 SomeMethod()
。所以在这一点上,我有几个问题:
A
的哪个实例调用了SomeMethod
?B
如何知道要调用委托(delegate)的实例? CLR 如何在这里工作?- 另外,
SomeMethod
是一个private 方法,那么B
为什么能够从类外部调用这个方法
?
编辑:
阅读前几个答案后,我开始知道 Delegate
有一个 Target
属性,在该属性上调用委托(delegate)。但是我无法真正理解这个 Target
属性到底是在哪一步设置的?谁定的?当我编写 b.SomeEvent += this.SomeMethod;
时,它是否也设置了 Target
属性?具体如何?
最佳答案
b.SomeEvent += this.SomeMethod
这里有很多糖分让您看不到真正发生的事情。写出来,它类似于这样:
b.SomeEvent.add(new MulticastDelegate(this, SomeMethod)); // not legal code
其中 add() 是事件的添加访问器,编译器会在您未明确声明自己的访问器时自动生成一个。委托(delegate)构造函数的第一个参数是您要询问的对象实例,即委托(delegate)对象的 Target 属性。请注意,这有副作用,事件订阅保留对您的 b
对象的引用。这会阻止它收集垃圾,这在调用事件时会很糟糕。
这也可能是一个问题,您可能会无意中泄漏对象引用。在您的代码中没有取消订阅事件处理程序的好方法,因此 A 对象将与您调用 h() 的 B 对象一样存在。
关于c# - 在哪个类委托(delegate)实例上被调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5436713/