Delegates


A delegate provides a way to encapsulate a method. It is an object that can refer to a method and can invoke the method to which it refers.

Delegates provide a built-in, language-supported mechanism for defining and executing callbacks. It provides an excellent mechanism to decouple the method being called from the actual caller. In fact, the caller of the delegate has no idea whether it is calling an instance method or a static method. To the caller, it is calling arbitrary code.

The principal advantage of a delegate is that the method that will be invoked by a delegate is not determined at compile time, but rather at runtime.

A delegate dynamically wires up a method caller to its target method. There are two aspects to a delegate: type and instance.

A delegate type defines a protocol to which the caller and target will conform, comprising a list of parameter types and a return type. A delegate instance is an object that refers to one or more target methods conforming to that protocol.

Delegate declarations look almost exactly like abstract method declarations, except for the delegate keyword. Ex:

public delegate double ComputeOutput( int iValueX, int iValueY );

When you instantiate an instance of a delegate, you must wire it up to a method to call when it is invoked. The method that you wire it up to could be either a static or an instance method that has a signature compatible with that of the delegate.

Thus, the parameter types and the return type must either match the delegate declaration or be implicitly convertible to the types in the delegate declaration.

using System;

public delegate double ComputeOutput( int iValueX, int iValueY ); // Delegate declaration

public class Computer
{
  public Computer ( double dFactor ) // Constructor   
  {
    this.dFactor = dFactor;
  }
  public double ComputeInstance( int iValueX, int iValueY ) // instance method
  {
    double dResult = (iValueX + iValueY) * dFactor;
    Console.WriteLine( "Instance Results: {0}", dResult );
    return dResult;
  }
  public static double ComputeStatic( int iValueX, int iValueY ) // static method
  {
    double dResult = (iValueX + iValueY) * 0.5;
    Console.WriteLine( "Static Result: {0}", dResult );
    return dResult;
  }
  private double dFactor;
}

public class MyComputer
{
  static void Main()
  {
    Computer oComputer1 = new Computer( 0.69 );
    Computer oComputer2 = new Computer( 0.76 );
    ComputeOutput delegate1 = new ComputeOutput (oComputer1.ComputeInstance );
    ComputeOutput delegate2 = new ComputeOutput (oComputer2.ComputeInstance );
    // points to a static method - use method group conversion
    ComputeOutput delegate3 = Computer.ComputeStatic; 
    double dTotal = delegate1( 7, 8 ) + delegate2( 9, 2 ) + delegate3( 4, 3 );
    Console.WriteLine( "Output: {0}", dTotal );
  }
}

Method Group Conversion allows you to simply assign the name of a method to a delegate, without using new or explicitly invoking the delegate’s constructor. 

Computer.StaticCompute is actually called a method group because the method could be overloaded and this name could refer to a group of methods. In this case, the method group Computer.StaticCompute has one method in it.
 
C# allows you to directly assign a delegate from a method group. When you create the delegate instances via new, you pass the method group in the constructor.

Introduction to Delegates



Related Post: Multicast Delegates (Multicasting)

No comments:

Post a Comment