Friday, January 19, 2018

Delegates

Before understanding Delegates, we first need to understand two concepts.
  1. Covariance:- A method can return a type that is derived from the delegate's return type.
  2. Contra-variance:- A method can take a parameter that is a base of delegate's parameter type.
Note: Covariance and Contra-variance are supported only for reference types and not for value types or for the void. Because memory structure for value types and void varies, whereas, the memory structure for the reference type is always a pointer.


  • Delegates ensure that the callback method is type-safe.
  • Delegates also integrate the ability to call multiple methods sequentially and calling of static methods as well as an instance method.

When we define a delegate compiler internally creates a complete class for that delegate

internal delegate Int32 PrintString(Int32 value);

internal class PrintString: System.MulticastDelegate
{
        //constructor
       public PrintString(Object @object, IntPtr method);

    //Method with the same prototype as specified by the source code.
   public Int32 Invoke(Int32 value)
   {
        Int32 result;
       Delegate [] delegateSet = _invocationList as Delegate[];
   
      if(delegateSet != null){
          foreach(PrintString p in delegateSet)
                result = d(value);
     }
     else {
            //The delegate identifies a single method to be called back
            // Call the callback method on the specified target object.
             result = _methodPtr.Invoke(_target, value);
        }
   }
    return result;
}
  • Delegates can wrap calls to instance methods as well as static methods. For instance methods, the delegate needs to know the instance of the object the method is going to operate on.
  • Delegate types can be defined within a type (nested within other types) or at a global scope. Basically, because delegates are classes, a delegate can be defined anywhere a class can be defined.


Delegate Chain

Delegate.Combine (+=) adds delegate object to the delegate chain.
Delegate.Remove(-=) removes delegate object from the delegate chain.

eg. PrintString psString1 = new PrintString(Program.PrintToConsole);

      PrintString psStringChain = (PrintString)Delegate.Combine(psStringChain, psString1)
   
      PrintString psStringChain = (PrintString)Delegate.Remove(psStringChain, psString1)

PrintString psString1 = new PrintString(Program.WriteToConsole);
PrintString psString2 = new PrintString(Program.WriteToCloud);
PrintString psString3 = new PrintString(new Program().WriteToFile);

PrintString psChain = null;


1) psChain += psString1;



2) psChain += psString2; (A new delegate object is created)



3) psChain += psString3;


4) psChain -= psString3;

When Remove(-=) is called, it scans the delegate array (from the end towards index 0).
A) If a match found and there is only one item left in the array, that array item is returned.

B) If a match found and there are multiple items left in the array, a new delegate object is created - the _invocationList array created and initialized will refer to all items in the original array except for the item being removed, and a reference to this new delegate object is returned.

C) If you are removing the only element in the chain, Remove returns null.

Note:- Each call to Remove removes just one delegate from the chain, it does not remove all delegates that have matching _target & _methodPtr fields.

GetInvocationList() --> Operates on a Multicast delegate and returns an array of Delegate reference where each reference points to one of the chain's delegate object

No comments:

Post a Comment