简体   繁体   English

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

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

Consider this code, 考虑一下这段代码

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();
          }
     }
 }

In this code snippet, SomeEvent.invoke() actually invokes SomeMethod() of class A . 在这段代码片段中, SomeEvent.invoke()实际上调用了A类的SomeMethod() So at this point, I've few questions: 所以在这一点上,我几乎没有问题:

  • On what instance of A , SomeMethod gets invoked? 在什么实例的ASomeMethod被调用? How does B know the instance on which the delegate to be invoked? B如何知道要调用委托的实例? How does CLR work here? CLR如何在这里工作?
  • Also, SomeMethod is a private method, then how come B is able to invoke this method from outside of the class A ? 另外, SomeMethod是一个私有方法,那么为什么B能够从A类外部调用这个方法呢?

EDIT: 编辑:

After reading first few answers, I came to know that Delegate has a Target property on which delegate gets invoked. 在阅读了前几个答案之后,我开始知道Delegate有一个Target属性,在该属性上调用了委托。 But I couldn't really understand as to at exactly what step this Target property is set? 但我真的不明白这个Target属性到底是什么步骤? Who set it? 是谁设定的? When I write b.SomeEvent += this.SomeMethod; 当我写b.SomeEvent += this.SomeMethod; , does it set the Target property as well? ,它是否也设置了Target属性? How exactly? 究竟怎么样?

 b.SomeEvent += this.SomeMethod

There's a lot of sugar here that prevents you from seeing what is really happening. 这里有很多糖会阻止你看到真正发生的事情。 Written out, it resembles this: 写出来,它类似于:

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

Where add() is the add accessor for the event, the compiler auto-generates one when you don't declare your own explicitly. 其中add()是事件的add访问器,当您没有显式声明自己的访问器时,编译器会自动生成一个。 The first argument to the delegate constructor is the object instance that you are asking about, the delegate object's Target property. 委托构造函数的第一个参数是您要询问的对象实例,即委托对象的Target属性。 Note that this has side-effects, the event subscription keeps a reference to your b object. 请注意,这会产生副作用,事件订阅会保留对b对象的引用。 Which prevents it from getting garbage collected, that would be rather bad when the event is invoked. 这可以防止它被垃圾收集,这在调用事件时会相当糟糕。

That can also be a problem, you can unintentionally leak the object reference. 这也可能是一个问题,你可以无意中泄漏对象引用。 There's no good way in your code to un-subscribe the event handler so the A object is going to live as long as the B object on which you called h(). 在代码中没有好的方法来取消订阅事件处理程序,因此只要你调用h()的B对象,A对象就会生存。

The delegate contains the target reference to call the method on. 委托包含调用方法的目标引用。 You can examine this with the Delegate.Target property. 您可以使用Delegate.Target属性进行检查。 In this case it will be called on the instance which f is called on. 在这种情况下,它将在调用f的实例上调用。 (It's null if you're calling a static method.) (如果您正在调用静态方法,则为null。)

As for the privacy - that's just one of the features of delegates. 至于隐私 - 这只是代表的一个特点。 You can only create the delegate within code which has access to a private method, but you can run it anywhere. 您只能在有权访问私有方法的代码中创建委托,但您可以任何地方运行它。 Think of this as being like implementing an interface by just calling a private method from the public interface implementation. 可以认为这就像通过从公共接口实现调用私有方法来实现接口一样。

On what instance of A, SomeMethod gets invoked? 在什么实例的A,SomeMethod被调用? How does B know the instance on which the delegate to be invoked? B如何知道要调用委托的实例? How does CLR work here? CLR如何在这里工作?

The delegate actually contains a reference to the actual instance. 委托实际上包含对实际实例的引用。 This will cause it to invoke on the specific instance on which it was called. 这将导致它在调用它的特定实例上调用。

Also, SomeMethod is a private method, then how come B is able to invoke this method from outside of the class A? 另外,SomeMethod是一个私有方法,那么为什么B能够从A类外部调用这个方法呢?

It doesn't execute the method directly - it executes the delegate . 它不直接执行方法 - 它执行委托 There's a difference here - the private constraint only applies to the method, but since the class itself creates the delegate, it has access to the method, so everything works fine. 这里有一点不同 - 私有约束仅适用于该方法,但由于类本身创建了委托,因此它可以访问该方法,因此一切正常。

  • Whatever instance was used when attaching to the event 无论在附加到事件时使用了什么实例
  • Because A passed a delegate representation to it outside of the class. 因为A在类之外传递了委托表示。

A particular Delegate instance has a Target property; 特定的Delegate实例具有Target属性; this represents the instance that will be used when invoking the delegate. 这表示调用委托时将使用的实例。

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

相关问题 将委托声明传递给 class,然后更改其要调用的值 - Passing delegate declaration to a class and then later changing its value to be invoked 一个类中的委托是什么意思? - What is the meaning of a delegate inside a class? 如果要调用的方法被垃圾回收,Dispatcher.Invoke会发生什么? - What happens to Dispatcher.Invoke if the method to be invoked gets garbage collected? 委托实例和方法指针之间有什么区别? - What is the difference between a delegate instance and a method pointer? 等待委托中调用的任务 - Wait on a task invoked in a delegate 找出哪个类调用了一个方法 - Find out what class invoked a method 委托声明和声明委托的类之间的关系是什么 - what is the relation between delegate declaration and the class in which the delegate is declared 有可能'overeride'(?)我的委托包装器被调用的方式? 所以代替meAction.Invoke()我可以只做meAction()? - Is it possible to 'overeride' (?) the way my delegate wrapper gets invoked? so instead of meAction.Invoke() I could just do meAction()? 如何从此类中的委托访问类的实例方法 - How to access an instance method of a class from the delegate which is in this class 订阅多次调用的委托 - Subscribing to a delegate that is invoked multiple times
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM