繁体   English   中英

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

[英]On what instance of class delegate gets invoked?

考虑一下这段代码

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() 所以在这一点上,我几乎没有问题:

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

编辑:

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

 b.SomeEvent += this.SomeMethod

这里有很多糖会阻止你看到真正发生的事情。 写出来,它类似于:

 b.SomeEvent.add(new MulticastDelegate(this, SomeMethod));     // not legal code

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

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

委托包含调用方法的目标引用。 您可以使用Delegate.Target属性进行检查。 在这种情况下,它将在调用f的实例上调用。 (如果您正在调用静态方法,则为null。)

至于隐私 - 这只是代表的一个特点。 您只能在有权访问私有方法的代码中创建委托,但您可以任何地方运行它。 可以认为这就像通过从公共接口实现调用私有方法来实现接口一样。

在什么实例的A,SomeMethod被调用? B如何知道要调用委托的实例? CLR如何在这里工作?

委托实际上包含对实际实例的引用。 这将导致它在调用它的特定实例上调用。

另外,SomeMethod是一个私有方法,那么为什么B能够从A类外部调用这个方法呢?

它不直接执行方法 - 它执行委托 这里有一点不同 - 私有约束仅适用于该方法,但由于类本身创建了委托,因此它可以访问该方法,因此一切正常。

  • 无论在附加到事件时使用了什么实例
  • 因为A在类之外传递了委托表示。

特定的Delegate实例具有Target属性; 这表示调用委托时将使用的实例。

暂无
暂无

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

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