/*
* 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;
}
}
}
Language Basics
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);
}
}
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);
}
}
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;
}
}
Using a delegate with a container class to sort the collection and return a sorted array using different sort 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.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'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'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[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.Components);
}
}
}
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");
}
}
}
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");
}
}
}