Delegates:Using Delegates

image_pdfimage_print

/*
A Programmer's Introduction to C# (Second Edition)
by Eric Gunnerson

Publisher: Apress L.P.
ISBN: 1-893115-62-3
*/
// 22 – DelegatesUsing 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.CompareItemsCallback sortByName =
new Container.CompareItemsCallback(Employee.CompareName);
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.Compare(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; } [/csharp]

The minimum implementation of a delegate

image_pdfimage_print

   

/*
C# Programming Tips &amp; 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));
        }
    }
}


           
          


Two delegates

image_pdfimage_print
   

/*
 * 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 &amp; 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;
    }
  }
}

           
          


Delegates can refer to instance methods, too

image_pdfimage_print

   

/*
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(&#039; &#039;, &#039;-&#039;); 
  }  
 
  // Remove spaces. 
  public string removeSpaces(string a) { 
    string temp = ""; 
    int i; 
 
    Console.WriteLine("Removing spaces."); 
    for(i=0; i < a.Length; i++) 
      if(a&#91;i&#93; != &#039; &#039;) temp += a&#91;i&#93;; 
 
    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); 
  } 
}


           
          


A simple delegate example

image_pdfimage_print

   

/*
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(&#039; &#039;, &#039;-&#039;); 
  }  
 
  // Remove spaces. 
  static string removeSpaces(string a) { 
    string temp = ""; 
    int i; 
 
    Console.WriteLine("Removing spaces."); 
    for(i=0; i < a.Length; i++) 
      if(a&#91;i&#93; != &#039; &#039;) temp += a&#91;i&#93;; 
 
    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); 
  } 
}


           
          


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

image_pdfimage_print

   


/*
C# Programming Tips &amp; 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;
    }
} 



           
          


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

image_pdfimage_print

   


/*
C# Programming Tips &amp; 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.ComponentModel;

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&#039;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 ("	" + emp);
            }

            // Sort the employees by last name and show the list.
            Console.WriteLine ("
Sorted by last name:");
            clsEmployee [] arr = SortList (SortBy.Name);
            foreach (clsEmployee emp in arr)
            {
                Console.WriteLine ("	" + emp);
            }

            // Sort the employees by ID number and show the list.
            Console.WriteLine ("
Sorted by employee ID:");
            arr = SortList (SortBy.ID);
            foreach (clsEmployee emp in arr)
            {
                Console.WriteLine ("	" + emp);
            }

            // Sort the employees by ZIP code and show the list.
            Console.WriteLine ("
Sorted by ZIP code:");
            arr = SortList (SortBy.ZIP);
            foreach (clsEmployee emp in arr)
            {
                Console.WriteLine ("	" + emp);
            }
        }
        // Define a method that will create the proper delegate according to
        // the sort that is needed.
        static clsEmployee [] SortList (SortBy iSort)
        {
            clsEmployeeContainer.CompareItems sort = null;
            switch (iSort)
            {
                case SortBy.Name:
                    sort = new clsEmployeeContainer.CompareItems(clsEmployee.CompareByName);
                    break;
                case SortBy.ID:
                    sort = new clsEmployeeContainer.CompareItems(clsEmployee.CompareByID);
                    break;
                case SortBy.ZIP:
                    sort = new clsEmployeeContainer.CompareItems(clsEmployee.CompareByZip);
                    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&#039;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.Compare (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.Compare (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.Components;
            // 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&#91;x + 1&#93;, arrEmployee&#91;x&#93;);
                   else
                       result = sort (arrEmployee&#91;x&#93;, arrEmployee&#91;x + 1&#93;);
                    // 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.Components);
        }
    }
}