Csharp/C Sharp/Language Basics/delegate

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

Arrays of Delegates

 
using System;
public delegate void Task();
public class Starter {
    public static void Main() {
        Task[] tasks = { MethodA, MethodB, MethodC };
        string resp;
        tasks[0]();
        tasks[1]();
        tasks[2]();
    }
    public static void MethodA() {
        Console.WriteLine("Doing TaskA");
    }
    public static void MethodB() {
        Console.WriteLine("Doing TaskB");
    }
    public static void MethodC() {
        Console.WriteLine("Doing TaskC");
    }
}


A simple delegate example

/*
C#: The Complete Reference 
by Herbert Schildt 
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/

// A simple delegate example.  
  
using System; 
 
// Declare a delegate.  
delegate string strMod(string str); 
 
public class DelegateTest { 
  // Replaces spaces with hyphens. 
  static string replaceSpaces(string a) { 
    Console.WriteLine("Replaces spaces with hyphens."); 
    return a.Replace(" ", "-"); 
  }  
 
  // Remove spaces. 
  static string removeSpaces(string a) { 
    string temp = ""; 
    int i; 
 
    Console.WriteLine("Removing spaces."); 
    for(i=0; i < a.Length; i++) 
      if(a[i] != " ") temp += a[i]; 
 
    return temp; 
  }  
 
  // Reverse a string. 
  static string reverse(string a) { 
    string temp = ""; 
    int i, j; 
 
    Console.WriteLine("Reversing string."); 
    for(j=0, i=a.Length-1; i >= 0; i--, j++) 
      temp += a[i]; 
 
    return temp; 
  } 
     
  public static void Main() {  
    // Construct a delegate. 
    strMod strOp = new strMod(replaceSpaces); 
    string str; 
 
    // Call methods through the delegate. 
    str = strOp("This is a test."); 
    Console.WriteLine("Resulting string: " + str); 
    Console.WriteLine(); 
      
    strOp = new strMod(removeSpaces); 
    str = strOp("This is a test."); 
    Console.WriteLine("Resulting string: " + str); 
    Console.WriteLine(); 
 
    strOp = new strMod(reverse); 
    str = strOp("This is a test."); 
    Console.WriteLine("Resulting string: " + str); 
  } 
}


Combining delegates Multiple delegates are combined using the Combine method, the plus operator (+), or the += assignment operator.

 
using System;
public delegate void DelegateClass();
public class Starter {
    public static void Main() {
        DelegateClass del = MethodA;
        del += MethodB;
        del();
    }
    public static void MethodA() {
        Console.WriteLine("MethodA...");
    }
    public static void MethodB() {
        Console.WriteLine("MethodB...");
    }
}


CreateDelegate and DynamicInvoke

 
using System;
using System.Reflection;
delegate void theDelegate(int arga, int argb);
class MyClass {
    public void MethodA(int arga, int argb) {
        Console.WriteLine("MyClass.MethodA called: {0} {1}", arga, argb);
    }
}
class Starter {
    static void Main() {
        Type tObj = typeof(System.MulticastDelegate);
        MyClass obj = new MyClass();
        Delegate del = Delegate.CreateDelegate(typeof(theDelegate), obj,"MethodA");
        del.DynamicInvoke(new object[] { 1, 2 });
    }
}


Define your own delegate

/*
Learning C# 
by Jesse Liberty
Publisher: O"Reilly 
ISBN: 0596003765
*/
 using System;
 namespace DelegatesAndEvents
 {
     class MyClassWithDelegate
     {
         // The delegate declaration.
         public delegate void StringDelegate(string s);
     }
     class MyImplementingClass
     {
         public static void WriteString(string s)
         {
             Console.WriteLine("Writing string {0}", s);
         }
         public static void LogString(string s)
         {
             Console.WriteLine("Logging string {0}", s);
         }
         public static void TransmitString(string s)
         {
             Console.WriteLine("Transmitting string {0}", s);
         }
     }
    public class TesterDelegatesAndEvents
    {
       public void Run()
       {
           // Define three StringDelegate objects.
           MyClassWithDelegate.StringDelegate
               Writer, Logger, Transmitter;
           // Define another StringDelegate
           // to act as the multicast delegate.
           MyClassWithDelegate.StringDelegate
               myMulticastDelegate;
           // Instantiate the first three delegates,
           // passing in methods to encapsulate.
           Writer = new MyClassWithDelegate.StringDelegate(
               MyImplementingClass.WriteString);
           Logger = new MyClassWithDelegate.StringDelegate(
               MyImplementingClass.LogString);
           Transmitter =
               new MyClassWithDelegate.StringDelegate(
               MyImplementingClass.TransmitString);
           // Invoke the Writer delegate method.
           Writer("String passed to Writer\n");
           // Invoke the Logger delegate method.
           Logger("String passed to Logger\n");
           // Invoke the Transmitter delegate method.
           Transmitter("String passed to Transmitter\n");
           // Tell the user you are about to combine
           // two delegates into the multicast delegate.
           Console.WriteLine(
               "myMulticastDelegate = Writer + Logger");
           // Combine the two delegates;  assign the result
           // to myMulticastDelegate
           myMulticastDelegate = Writer + Logger;
           // Call the delegated methods; two methods
           // will be invoked.
           myMulticastDelegate(
               "First string passed to Collector");
           // Tell the user you are about to add
           // a third delegate to the multicast.
           Console.WriteLine(
               "\nmyMulticastDelegate += Transmitter");
           // Add the third delegate.
           myMulticastDelegate += Transmitter;
           // Invoke the three delegated methods.
           myMulticastDelegate(
               "Second string passed to Collector");
           // Tell the user you are about to remove
           // the Logger delegate.
           Console.WriteLine(
               "\nmyMulticastDelegate -= Logger");
           // Remove the Logger delegate.
           myMulticastDelegate -= Logger;
           // Invoke the two remaining delegated methods.
           myMulticastDelegate(
               "Third string passed to Collector");
       }
       [STAThread]
       static void Main()
       {
          TesterDelegatesAndEvents t = new TesterDelegatesAndEvents();
          t.Run();
       }
    }
 }


Delegates can refer to instance methods, too

/*
C#: The Complete Reference 
by Herbert Schildt 
Publisher: Osborne/McGraw-Hill (March 8, 2002)
ISBN: 0072134852
*/

// Delegates can refer to instance methods, too. 
  
using System; 
 
// Declare a delegate.  
delegate string strMod(string str); 
class StringOps {
  // Replaces spaces with hyphens. 
  public string replaceSpaces(string a) { 
    Console.WriteLine("Replaces spaces with hyphens."); 
    return a.Replace(" ", "-"); 
  }  
 
  // Remove spaces. 
  public string removeSpaces(string a) { 
    string temp = ""; 
    int i; 
 
    Console.WriteLine("Removing spaces."); 
    for(i=0; i < a.Length; i++) 
      if(a[i] != " ") temp += a[i]; 
 
    return temp; 
  }  
 
  // Reverse a string. 
  public string reverse(string a) { 
    string temp = ""; 
    int i, j; 
 
    Console.WriteLine("Reversing string."); 
    for(j=0, i=a.Length-1; i >= 0; i--, j++) 
      temp += a[i]; 
 
    return temp; 
  } 
} 
 
public class DelegateTest1 {   
  public static void Main() { 
    StringOps so = new StringOps(); // create an instance of StringOps
 
    // Construct a delegate. 
    strMod strOp = new strMod(so.replaceSpaces); 
    string str; 
 
    // Call methods through delegates. 
    str = strOp("This is a test."); 
    Console.WriteLine("Resulting string: " + str); 
    Console.WriteLine(); 
      
    strOp = new strMod(so.removeSpaces); 
    str = strOp("This is a test."); 
    Console.WriteLine("Resulting string: " + str); 
    Console.WriteLine(); 
 
    strOp = new strMod(so.reverse); 
    str = strOp("This is a test."); 
    Console.WriteLine("Resulting string: " + str); 
  } 
}


Delegates:Multicasting

using System;
public class DelegatesMulticasting
{
    delegate void ProcessHandler(string message);
    
    static public void Process(string message)
    {
        Console.WriteLine("Test.Process(\"{0}\")", message);
    }
    public static void Main()
    {
        User user = new User("George");
        
        ProcessHandler ph = new ProcessHandler(user.Process);
        ph = (ProcessHandler) Delegate.rubine(ph, new ProcessHandler(Process));
        
        ph("Wake Up!");        
    }
}
public class User
{
    string name;
    public User(string name)
    {
        this.name = name;
    }    
    public void Process(string message)
    {
        Console.WriteLine("{0}: {1}", name, message);
    }
}


Delegates to Instance Members

using System;
public class DelegatestoInstanceMembers
{
    delegate void ProcessHandler(string message);
    
    public static void Main()
    {
        User aUser = new User("George");
        ProcessHandler ph = new ProcessHandler(aUser.Process);
        
        ph("Wake Up!");        
    }
}
public class User
{
    string name;
    public User(string name)
    {
        this.name = name;
    }    
    public void Process(string message)
    {
        Console.WriteLine("{0}: {1}", name, message);
    }
}


Delegates:Using Delegates

/*
A Programmer"s Introduction to C# (Second Edition)
by Eric Gunnerson
Publisher: Apress  L.P.
ISBN: 1-893115-62-3
*/
// 22 - Delegates\Using Delegates
// copyright 2000 Eric Gunnerson
using System;

public class DelegatesUsingDelegates
{
    public static void Main()
    {
        Container employees = new Container();
        // create and add some employees here
        
        // create delegate to sort on names, and do the sort
        Container.rupareItemsCallback sortByName = 
        new Container.rupareItemsCallback(Employee.rupareName);
        employees.Sort(sortByName);            
        // employees is now sorted by name
    }
}
public class Container
{
    public delegate int CompareItemsCallback(object obj1, object obj2);
    public void Sort(CompareItemsCallback compare)
    {
        // not a real sort, just shows what the
        // inner loop code might do
        int x = 0;
        int y = 1;
        object    item1 = arr[x];
        object item2 = arr[y];
        int order = compare(item1, item2);
    }
    object[]    arr = new object[1];    // items in the collection
}
public class Employee
{
    Employee(string name, int id)
    {
        this.name = name;
        this.id = id;
    }
    public static int CompareName(object obj1, object obj2)
    {
        Employee emp1 = (Employee) obj1;
        Employee emp2 = (Employee) obj2;
        return(String.rupare(emp1.name, emp2.name));
    }
    public static int CompareId(object obj1, object obj2)
    {
        Employee emp1 = (Employee) obj1;
        Employee emp2 = (Employee) obj2;
        
        if (emp1.id > emp2.id)
        return(1);
        if (emp1.id < emp2.id)
        return(-1);
        else
        return(0);
    }
    string    name;
    int    id;
}


Demonstrate getting and printing the invocation list for a delegate

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
// InvkList.cs -- Demonstrate getting and printing the invocation list
//                for a delegate.
//
//                Compile this program with the following command line:
//                    C:>csc InvkList.cs
using System;
using System.Reflection;
namespace nsDelegates
{
    public class DelegatesList
    {
        public delegate void ListHandler ();
        public ListHandler DoList;
        static public void Main ()
        {
            DelegatesList main = new DelegatesList ();
            main.DoList += new ListHandler (DelegateMethodOne);
            main.DoList += new ListHandler (DelegateMethodThree);
            main.DoList += new ListHandler (DelegateMethodTwo);
            Delegate [] dlgs = main.DoList.GetInvocationList ();
            foreach (Delegate dl in dlgs)
            {
                MethodInfo info = dl.Method;
                Console.WriteLine (info.Name);
                info.Invoke (main, null);
            }
        }
        static void DelegateMethodOne ()
        {
            Console.WriteLine ("In delegate method one");
        }
        static void DelegateMethodTwo ()
        {
            Console.WriteLine ("In delegate method two");
        }
        static void DelegateMethodThree ()
        {
            Console.WriteLine ("In delegate method three");
        }
    }
}


Demonstrates adding multiple methods to a delegate

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
 
// MultiDlg.cs -- Demonstrates adding multiple methods to a delegate.
//
//                Compile this program with the following command line
//                    C:>csc MultiDlg.cs
using System;
namespace nsDelegates
{
    public class MultiDlg
    {
        public delegate void MultiMethod ();
        static public void Main ()
        {
            MultiMethod dlg;
// Assign the first method to the delegate.
            dlg = new MultiMethod (FirstDelegate);
// Call it to show the first method is being called
            dlg ();
// Add a second method to the delegate.
            dlg += new MultiMethod (SecondDelegate);
// Call it to show both methods execute.
            Console.WriteLine ();
            dlg ();
// Remove the first method from the delegate.
            dlg -= new MultiMethod (FirstDelegate);
// Call it to show that only the second method executes
            Console.WriteLine ();
            dlg ();
        }
        static public void FirstDelegate()
        {
            Console.WriteLine ("First delegate called");
        }
        static public void SecondDelegate()
        {
            Console.WriteLine ("Second delegate called");
        }
    }
}


Demonstrates a simple form of a delegate

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
// SimpDlgt.cs -- Demonstrates a simple form of a delegate
//
//                Compile this program using the following command line:
//                    C:>csc SimpDlgt.cs
using System;
namespace nsDelegate
{
// Declare the delegate. This actually creates a new class definition.
    delegate double MathOp (double value);
    public class SimpDlgt
    {
        static public void Main ()
        {
// Declare an object of the delegate type.
            MathOp DoMath;
// Create the delgate object using a method name.
            DoMath = new MathOp (GetSquare);
// Execute the delegate. This actually calls the Invoke() method.
            double result = DoMath (3.14159);
// Show the result.
            Console.WriteLine (result);
// Assign another method to the delegate object
            DoMath = new MathOp (GetSquareRoot);
// Call the delegate again.
            result = DoMath (3.14159);
// Show the result.
            Console.WriteLine (result);
        }
// Return the square of the argument.
        static double GetSquare (double val)
        {
            return (val * val);
        }
// Return the square root of the argument.
        static double GetSquareRoot (double val)
        {
            return (Math.Sqrt (val));
        }
    }
}


Demonstrates combining and removing delegates to create new delegates

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
// DlgOps.cs -- demonstrates combining and removing delegates to create
//              new delegates.
//
//              Compile this program with the following command line:
//                  C:>csc DlgOps.cs
using System;
namespace nsDelegates
{
    public class DelegatesSample
    {
        public delegate void MathHandler (double val);
        static public void Main ()
        {
            DelegatesSample main = new DelegatesSample ();
            MathHandler dlg1, dlg2, dlg3;
            dlg1 = new MathHandler (main.TheSquareRoot);
            dlg2 = new MathHandler (main.TheSquare);
            dlg3 = new MathHandler (main.TheCube);
// Combine the delegates so you can execute all three at one on one value
            MathHandler dlgCombo = dlg1 + dlg2 + dlg3;
            Console.WriteLine ("Executing the combined delegate");
            dlgCombo (42);
// Now remove the second delegate
            MathHandler dlgMinus = dlgCombo - dlg2;
            Console.WriteLine ("\r\nExecuting the delegate with the second removed");
            dlgMinus (42);
// Show that the individual delegates are stil available
// Execute the delegates one at a time using different values
            Console.WriteLine ("\r\nExecute the delegates individually:");
            dlg1 (64);
            dlg2 (12);
            dlg3 (4);
        }
        public void TheSquareRoot (double val)
        {
            Console.WriteLine ("The square root of " + val + " is " + Math.Sqrt (val));
        }
        public void TheSquare (double val)
        {
            Console.WriteLine ("The square of " + val + " is " + val * val);
        }
        public void TheCube (double val)
        {
            Console.WriteLine ("The cube of " + val + " is " + val * val * val);
        }
    }
}


Demonstrate using a static delegate without declaring an instance of the class

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
// StaticDl.cs -- Demonstrate using a static delegate without declaring
//                an instance of the class.
//
//                Compile this program with the following command line:
//                    C:>csc StaticDl.cs
using System;
namespace nsDelegates
{
    public class StaticDl
    {
        public delegate void StringHandler (string str);
        static public StringHandler DoString;
        static public void Main ()
        {
// Create a delegate in this class
            DoString = new StringHandler (ShowString);
            DoString ("Static delegate called");
//
// Show that the static constructor in another class is shared by instances
            clsDelegate.DoMath = new clsDelegate.MathHandler (SquareRoot);
            clsDelegate dlg1 = new clsDelegate (49);
            clsDelegate dlg2 = new clsDelegate (3.14159);
        }
// The method used with the string delegate
        static private void ShowString (string str)
        {
            Console.WriteLine (str);
        }
// The method used with the double delegate
        static private double SquareRoot (double val)
        {
            double result = Math.Sqrt (val);
            Console.WriteLine ("The square root of " + val + " is " + result);
            return (result);
        }
    }
    class clsDelegate
    {
        public delegate double MathHandler (double val);
        static public MathHandler DoMath;
// The constructor invokes the delegate if it is not null.
        public clsDelegate (double val)
        {
            value = val;
            if (DoMath != null)
                sqrt = DoMath (value);
        }
        double value;
        double sqrt = 0;
    }
}


illustrates the use of a delegate 2

/*
Mastering Visual C# .NET
by Jason Price, Mike Gunderloy
Publisher: Sybex;
ISBN: 0782129110
*/
/*
  Example12_1.cs illustrates the use of a delegate
*/
using System;

// declare the DelegateCalculation delegate class
public delegate double DelegateCalculation(
  double acceleration, double time
);

// declare the MotionCalculations class
class MotionCalculations
{
  // FinalSpeed() calculates the final speed
  public static double FinalSpeed(
    double acceleration, double time
  )
  {
    double finalSpeed = acceleration * time;
    return finalSpeed;
  }
  // Distance() calculates the distance traveled
  public static double Distance(
    double acceleration, double time
  )
  {
    double distance = acceleration * Math.Pow(time, 2) / 2;
    return distance;
  }
}

public class Example12_1
{
  public static void Main()
  {
    // declare and initialize the acceleration and time
    double acceleration = 10;  // meters per second per second
    double time = 5;  // seconds
    Console.WriteLine("acceleration = " + acceleration +
      " meters per second per second");
    Console.WriteLine("time = " + time + " seconds");
    // create a delegate object that calls
    // MotionCalculations.FinalSpeed
    DelegateCalculation myDelegateCalculation =
      new DelegateCalculation(MotionCalculations.FinalSpeed);
    // calculate and display the final speed
    double finalSpeed = myDelegateCalculation(acceleration, time);
    Console.WriteLine("finalSpeed = " + finalSpeed +
      " meters per second");
    // set the delegate method to MotionCalculations.Distance
    myDelegateCalculation =
      new DelegateCalculation(MotionCalculations.Distance);
    // calculate and display the distance traveled
    double distance = myDelegateCalculation(acceleration, time);
    Console.WriteLine("distance = " + distance + " meters");
  }
}


illustrates the use of a delegate that calls object methods

/*
Mastering Visual C# .NET
by Jason Price, Mike Gunderloy
Publisher: Sybex;
ISBN: 0782129110
*/
/*
  Example12_3.cs illustrates the use of a delegate
  that calls object methods
*/
using System;

// declare the DelegateCalculation delegate class
public delegate string DelegateDescription();

// declare the Person class
class Person
{
  // declare two private fields
  private string name;
  private int age;
  // define a constructor
  public Person(string name, int age)
  {
    this.name = name;
    this.age = age;
  }
  // define a method that returns a string containing
  // the person"s name and age
  public string NameAndAge()
  {
    return(name + " is " + age + " years old");
  }
}

// declare the Car class
class Car
{
  // declare two private fields
  private string model;
  private int topSpeed;
  // define a constructor
  public Car(string model, int topSpeed)
  {
    this.model = model;
    this.topSpeed = topSpeed;
  }
  // define a method that returns a string containing
  // the car"s model and top speed
  public string MakeAndTopSpeed()
  {
    return("The top speed of the " + model + " is " +
      topSpeed + " mph");
  }
}

public class Example12_3
{
  public static void Main()
  {
    // create a Person object named myPerson
    Person myPerson = new Person("Jason Price", 32);
    // create a delegate object that calls myPerson.NameAndAge()
    DelegateDescription myDelegateDescription =
      new DelegateDescription(myPerson.NameAndAge);
    // call myPerson.NameAndAge() through myDelegateDescription
    string personDescription = myDelegateDescription();
    Console.WriteLine("personDescription = " + personDescription);
    // create a Car object named myCar
    Car myCar = new Car("MR2", 140);
    // set myDelegateDescription to call myCar.MakeAndTopSpeed()
    myDelegateDescription =
      new DelegateDescription(myCar.MakeAndTopSpeed);
    // call myCar.MakeAndTopSpeed() through myDelegateDescription
    string carDescription = myDelegateDescription();
    Console.WriteLine("carDescription = " + carDescription);
  }
}


illustrates the use of a multicast delegate

/*
Mastering Visual C# .NET
by Jason Price, Mike Gunderloy
Publisher: Sybex;
ISBN: 0782129110
*/
/*
  Example12_2.cs illustrates the use of a multicast delegate
*/
using System;

// declare the DelegateCalculation delegate class
public delegate void DelegateCalculation(
  double acceleration, double time
);

// declare the MotionCalculations class
class MotionCalculations
{
  // FinalSpeed() calculates the final speed
  public static void FinalSpeed(
    double acceleration, double time
  )
  {
    double finalSpeed = acceleration * time;
    Console.WriteLine("finalSpeed = " + finalSpeed +
      " meters per second");
  }
  // Distance() calculates the distance traveled
  public static void Distance(
    double acceleration, double time
  )
  {
    double distance = acceleration * Math.Pow(time, 2) / 2;
    Console.WriteLine("distance = " + distance + " meters");
  }
}

public class Example12_2
{
  public static void Main()
  {
    // declare and initialize the acceleration and time
    double acceleration = 10;  // meters per second per second
    double time = 5;  // seconds
    Console.WriteLine("acceleration = " + acceleration +
      " meters per second per second");
    Console.WriteLine("time = " + time + " seconds");
    // create delegate object that call the
    // MotionCalculations.FinalSpeed() and
    // MotionCalculations.Distance() methods
    DelegateCalculation myDelegateCalculation1 =
      new DelegateCalculation(MotionCalculations.FinalSpeed);
    DelegateCalculation myDelegateCalculation2 =
      new DelegateCalculation(MotionCalculations.Distance);
    // create a multicast delegate object from
    // myDelegateCalculation1 and
    // myDelegateCalculation2
    DelegateCalculation myDelegateCalculations =
      myDelegateCalculation1 + myDelegateCalculation2;
    // calculate and display the final speed and distance
    // using myDelegateCalculations
    myDelegateCalculations(acceleration, time);
  }
}


Late Binding Delegates: A delegate is a repository of type-safe function pointers.

 
using System;
using System.Reflection;
delegate void XDelegate(int arga, int argb);
class MyClass {
    public void MethodA(int arga, int argb) {
        Console.WriteLine("MyClass.MethodA called: {0} {1}", arga, argb);
    }
}
class Starter {
    static void Main() {
        MyClass obj = new MyClass();
        XDelegate delObj = new XDelegate(obj.MethodA);
        delObj.Invoke(1, 2);
        delObj(3, 4);
    }
}


Lifetime of outer variables is aligned with the delegate

 
using System;
public delegate void DelegateClass(out int var);
public class Starter {
    public static void Main() {
        DelegateClass del = MethodA();
        int var;
        del(out var);
        del(out var);
        del(out var);
        Console.WriteLine(var);
    }
    public static DelegateClass MethodA() {
        int increment = 0;
        return delegate(out int var) {
            var = ++increment;
        };
    }
}


The minimum implementation of a delegate

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
//  Delegate.cs - Demonstrates the minimum implementation of a delegate
//                Compile this program with the following command line:
//                    C:>csc Delegate.cs
//
namespace nsDelegate
{
    using System;
    public class Delegate21
    {
//  Declare the delegate type
        public delegate double MathHandler (double val);
//  Declare the variable that will hold the delegate
        public MathHandler DoMath;
        static public void Main ()
        {
            double val = 31.2;
            double result;
            Delegate21 main = new Delegate21();
//  Create the first delegate
            main.DoMath = new Delegate21.MathHandler (main.Square);
//  Call the function through the delegate
            result = main.DoMath (val);
            Console.WriteLine ("The square of {0,0:F1} is {1,0:F3}",
                                val,  result);
//  Create the second delegate
            main.DoMath = new Delegate21.MathHandler (main.SquareRoot);
//  Call the function through the delegate
            result = main.DoMath (val);
            Console.WriteLine ("The square root of {0,0:F1} is {1,0:F3}",
                               val, result);
        }
        public double Square (double val)
        {
            return (val * val);
        }
        public double SquareRoot (double val)
        {
            return (Math.Sqrt (val));
        }
    }
}


The publisher/subscriber relationship is a one-to-many relationship.

 
using System;
class Publisher {
    public event EventHandler MyEvent;
}
public class Subscriber {
    public static void Handler(object obj, EventArgs args) {
    }
    public static void Main() {
        Publisher pub = new Publisher();
        pub.MyEvent += Handler;
        // other processing
    }
}


the syntax of the GetInvocationList method: delegate [] GetInvocationList()

 
using System;
public delegate void DelegateClass();
public class Starter {
    public static void Main() {
        DelegateClass del = (DelegateClass)
        DelegateClass.rubine(new DelegateClass[] { MethodA, MethodB, MethodA, MethodB });
        del();
        foreach (DelegateClass item in
            del.GetInvocationList()) {
            Console.WriteLine(item.Method.Name + " in invocation list.");
        }
    }
    public static void MethodA() {
        Console.WriteLine("MethodA...");
    }
    public static void MethodB() {
        Console.WriteLine("MethodB...");
    }
}


To remove delegates from a multicast delegate, use the Remove method, the minus operator (-), or the -= assignment operator.

 
using System;
public delegate void DelegateClass();
public class Starter {
    public static void Main(){
         DelegateClass del=MethodA;
         del+=MethodB;
         del+=MethodC;
         del=del-MethodB;
         del();
     }
    public static void MethodA() {
        Console.WriteLine("MethodA...");
    }
    public static void MethodB() {
        Console.WriteLine("MethodB...");
    }
    public static void MethodC() {
        Console.WriteLine("MethodC...");
    }
}


Two delegates

/*
 * C# Programmers Pocket Consultant
 * Author: Gregory S. MacBeth
 * Email: gmacbeth@comporium.net
 * Create Date: June 27, 2003
 * Last Modified Date:
 */
using System;
namespace Client.Chapter_8___Delegates_and_Events
{
  public class DelegatesChapter_8___Delegates_and_Events
  {
    delegate int MyDelegate(string s);
    static void Main(string[] args)
    {
      MyDelegate Del1 = new MyDelegate(DoSomething);
      MyDelegate Del2 = new MyDelegate(DoSomething2);
      string MyString = "Hello World";
      Del1(MyString);
      Del2(MyString);
      //Or you can Multicast delegates by doing this
      MyDelegate Multicast = null;
      Multicast += new MyDelegate(DoSomething);
      Multicast += new MyDelegate(DoSomething2);
      //Both DoSomething & DoSomething2 will be fired
      //in the order they are added to the delegate
      Multicast(MyString);
      Multicast -= new MyDelegate(DoSomething2);
    }
    static int DoSomething(string s)
    {
      return 0;
    }
    static int DoSomething2(string s)
    {
      return 0;
    }
  }
}


Using a delegate with a container class o sort the collection and return a sorted array using different ort criteria

/*
C# Programming Tips & Techniques
by Charles Wright, Kris Jamsa
Publisher: Osborne/McGraw-Hill (December 28, 2001)
ISBN: 0072193794
*/
 
// SortEmpl.cs -- Demonstrates using a delegate with a container class to
//                sort the collection and return a sorted array using different
//                sort criteria.
//
//                Compile this program with the following command line:
//                    C:>csc SortEmpl.cs
using System;
using System.ruponentModel;
namespace nsDelegates
{
    public class SortEmpl
    {
        // Declare an enum for the sort methods.
        enum SortBy {Name, ID, ZIP};
        // Create a container to get the clsEmployee object collection
        static public clsEmployeeContainer container = new clsEmployeeContainer ();
        static public void Main ()
        {
            container.Add (new clsEmployee ("John", "Smith", "87678", 1234));
            container.Add (new clsEmployee ("Marty", "Thrush", "80123", 1212));
            container.Add (new clsEmployee ("Milton", "Aberdeen", "87644", 1243));
            container.Add (new clsEmployee ("Marion", "Douglas", "34567", 3454));
            container.Add (new clsEmployee ("Johnathon", "Winters", "53422", 3458));
            container.Add (new clsEmployee ("William", "Marmouth", "12964", 3658));
            container.Add (new clsEmployee ("Miles", "O"Brien", "63445", 6332));
            container.Add (new clsEmployee ("Benjamin", "Sisko", "57553", 9876));
            // Show the unsorted employee list.
            Console.WriteLine ("Unsorted employee list:");
            ComponentCollection collectionList = container.GetEmployees();
            foreach (clsEmployee emp in collectionList)
            {
                Console.WriteLine ("\t" + emp);
            }
            // Sort the employees by last name and show the list.
            Console.WriteLine ("\r\nSorted by last name:");
            clsEmployee [] arr = SortList (SortBy.Name);
            foreach (clsEmployee emp in arr)
            {
                Console.WriteLine ("\t" + emp);
            }
            // Sort the employees by ID number and show the list.
            Console.WriteLine ("\r\nSorted by employee ID:");
            arr = SortList (SortBy.ID);
            foreach (clsEmployee emp in arr)
            {
                Console.WriteLine ("\t" + emp);
            }
            // Sort the employees by ZIP code and show the list.
            Console.WriteLine ("\r\nSorted by ZIP code:");
            arr = SortList (SortBy.ZIP);
            foreach (clsEmployee emp in arr)
            {
                Console.WriteLine ("\t" + emp);
            }
        }
        // Define a method that will create the proper delegate according to
        // the sort that is needed.
        static clsEmployee [] SortList (SortBy iSort)
        {
            clsEmployeeContainer.rupareItems sort = null;
            switch (iSort)
            {
                case SortBy.Name:
                    sort = new clsEmployeeContainer.rupareItems(clsEmployee.rupareByName);
                    break;
                case SortBy.ID:
                    sort = new clsEmployeeContainer.rupareItems(clsEmployee.rupareByID);
                    break;
                case SortBy.ZIP:
                    sort = new clsEmployeeContainer.rupareItems(clsEmployee.rupareByZip);
                    break;
            }
            // Do the sort and return the sorted array to the caller.
            return (container.SortItems (sort, false));
        }
    }
    public class clsEmployee : Component
    {
        // Define an employee class to hold one employee"s information.
        public clsEmployee (string First, string Last, string Zip, int ID)
        {
            FirstName = First;
            LastName = Last;
            EmployeeID = ID;
            ZipCode = Zip;
        }
        public string  FirstName;
        public string  LastName;
        public string  ZipCode;
        public int      EmployeeID;
        // Define a method to sort by name
        static public int CompareByName (object o1, object o2)
        {
            clsEmployee emp1 = (clsEmployee) o1;
            clsEmployee emp2 = (clsEmployee) o2;
            return (String.rupare (emp1.LastName, emp2.LastName));
        }
        // Define a method to sort by ZIP code
        static public int CompareByZip (object o1, object o2)
        {
            clsEmployee emp1 = (clsEmployee) o1;
            clsEmployee emp2 = (clsEmployee) o2;
            return (String.rupare (emp1.ZipCode, emp2.ZipCode));
        }
        // Define a method to sort by employee ID number.
        static public int CompareByID (object o1, object o2)
        {
            clsEmployee emp1 = (clsEmployee) o1;
            clsEmployee emp2 = (clsEmployee) o2;
            return (emp1.EmployeeID - emp2.EmployeeID);
        }
        // Override ToString() for diagnostic purposes
        public override string ToString ()
        {
            return (FirstName + " " + LastName + ", ZIP " + ZipCode + ", ID "  + EmployeeID);
        }
    }
    // Derive a class to hold the clsEmployee objects
    public class clsEmployeeContainer
    {
        private Container cont = new Container();
        public void Add (clsEmployee empl)
        {
            cont.Add (empl);
        }
        // Declare an array to return to the caller
        clsEmployee [] arrEmployee;
        // Declare a delegate to compare one employee object to another
        public delegate int CompareItems (object obj1, object obj2);
        // Define a sort function that takes a delegate as a parameter. The Reverse
        // parameter can be used to reverse the sort.
        public clsEmployee [] SortItems (CompareItems sort, bool Reverse)
        {
            // Get the clsEmployee objects in the container.
            ComponentCollection employees = cont.ruponents;
            // Create an array large enough to hold the references
            arrEmployee = new clsEmployee[employees.Count];
            // Copy the collection into the reference. The Container class will not
            // let us sort the collection itself.
            employees.CopyTo (arrEmployee, 0);
            // Do a simple bubble sort. There are more efficient sorting algorithms,
            // but a simple sort is all we need.
            while (true)
            {
                int sorts = 0;
                for (int x = 0; x < arrEmployee.Length - 1; ++x)
                {
                   int result;
                    // Sort in the reverse order if if the Reverse parameter equals true
                   if (Reverse == true)
                       result = sort (arrEmployee[x + 1], arrEmployee[x]);
                   else
                       result = sort (arrEmployee[x], arrEmployee[x + 1]);
                    // Reverse the two elements if the result is greater than zero
                   if (result > 0)
                   {
                       clsEmployee temp = arrEmployee[x];
                       arrEmployee[x] = arrEmployee[x+1];
                       arrEmployee[x+1] = temp;
                       ++sorts;
                   }
                }
                // If we did no sorts on this go around, the sort is complete.
                if (sorts == 0)
                    break;
            }
            // Return the sorted array to the caller.
            return (arrEmployee);
        }
        // Return the collection to the caller.
        public ComponentCollection GetEmployees ()
        {
            return (cont.ruponents);
        }
    }
}