简体   繁体   中英

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 . So at this point, I've few questions:

  • On what instance of A , SomeMethod gets invoked? How does B know the instance on which the delegate to be invoked? How does CLR work here?
  • Also, SomeMethod is a private method, then how come B is able to invoke this method from outside of the class A ?

EDIT:

After reading first few answers, I came to know that Delegate has a Target property on which delegate gets invoked. But I couldn't really understand as to at exactly what step this Target property is set? Who set it? When I write b.SomeEvent += this.SomeMethod; , does it set the Target property as well? 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. The first argument to the delegate constructor is the object instance that you are asking about, the delegate object's Target property. Note that this has side-effects, the event subscription keeps a reference to your b object. 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().

The delegate contains the target reference to call the method on. You can examine this with the Delegate.Target property. In this case it will be called on the instance which f is called on. (It's null if you're calling a static method.)

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? How does B know the instance on which the delegate to be invoked? How does CLR work here?

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?

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 particular Delegate instance has a Target property; this represents the instance that will be used when invoking the delegate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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