Csharp/C Sharp/Language Basics/delegate

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

Arrays of Delegates

<source lang="csharp"> 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");
   }

}

</source>


A simple delegate example

<source lang="csharp"> /* 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); 
 } 

}


      </source>


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

<source lang="csharp"> 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...");
   }

}

</source>


CreateDelegate and DynamicInvoke

<source lang="csharp"> 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 });
   }

}

</source>


Define your own delegate

<source lang="csharp"> /* 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();
      }
   }
}
          
      </source>


Delegates can refer to instance methods, too

<source lang="csharp"> /* 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); 
 } 

}


      </source>


Delegates:Multicasting

<source lang="csharp"> 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);
   }

}


      </source>


Delegates to Instance Members

<source lang="csharp"> 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);
   }

}

      </source>


Delegates:Using Delegates

<source lang="csharp"> /* 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;

}


      </source>


Demonstrate getting and printing the invocation list for a delegate

<source lang="csharp"> /* 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");
       }
   }

}


      </source>


Demonstrates adding multiple methods to a delegate

<source lang="csharp"> /* 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");
       }
   }

}


      </source>


Demonstrates a simple form of a delegate

<source lang="csharp"> /* 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));
       }
   }

}


      </source>


Demonstrates combining and removing delegates to create new delegates

<source lang="csharp"> /* 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);
       }
   }

}


      </source>


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

<source lang="csharp"> /* 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;
   }

}


      </source>


illustrates the use of a delegate 2

<source lang="csharp"> /* 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");
 }

}

      </source>


illustrates the use of a delegate that calls object methods

<source lang="csharp"> /* 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);
 }

}

      </source>


illustrates the use of a multicast delegate

<source lang="csharp"> /* 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);
 }

}

      </source>


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

<source lang="csharp"> 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);
   }

}

</source>


Lifetime of outer variables is aligned with the delegate

<source lang="csharp"> 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;
       };
   }

}

</source>


The minimum implementation of a delegate

<source lang="csharp"> /* 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));
       }
   }

}


      </source>


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

<source lang="csharp"> 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
   }

}

</source>


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

<source lang="csharp"> 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...");
   }

}

</source>


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

<source lang="csharp"> 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...");
   }

}

</source>


Two delegates

<source lang="csharp"> /*

* 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;
   }
 }

}

      </source>


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

<source lang="csharp"> /* 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);
       }
   }

}


      </source>