Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 668
Nawaz Avatar asked Mar 25 '11 18:03

Nawaz


People also ask

How do I invoke a delegate?

Create the delegate and matching procedures Create a delegate named MySubDelegate . Declare a class that contains a method with the same signature as the delegate. Define a method that creates an instance of the delegate and invokes the method associated with the delegate by calling the built-in Invoke method.

Why delegates why not call methods directly?

If you think of delegates as being similar to interface definitions for a specific type of method, you can start to see why delegates exist. They allow clients of our delegates to ignore all the details of their implementations - even their names!

What is a class delegate?

A delegate is a reference type variable that holds the reference to a method. The reference can be changed at runtime. Delegates are especially used for implementing events and the call-back methods. All delegates are implicitly derived from the System. Delegate class.

Why we use delegates in C# with example?

Delegates in C# are similar to function pointers in C++, but C# delegates are type safe. You can pass methods as parameters to a delegate to allow the delegate to point to the method. Delegates are used to define callback methods and implement event handling, and they are declared using the “delegate” keyword.


Video Answer


3 Answers

 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().

like image 143
Hans Passant Avatar answered Oct 05 '22 06:10

Hans Passant


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.

like image 40
Jon Skeet Avatar answered Oct 05 '22 04:10

Jon Skeet


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.

like image 31
Reed Copsey Avatar answered Oct 05 '22 05:10

Reed Copsey