Here's what I sent to a coworker:
Basically delegates can be used for Callbacks, Events and Asynchronous processing.
Here’s some sample code, copy and paste each example to a new command line project.
//Callbacks
//-------------------------------------------------------------------------------------------------------
delegate double DiscountRule(); // Declaration
delegate string MessageFormat(); // Declaration
class Message
{
public string Instance() { return "You save {0:C}"; }
public static string Class() { return "You are buying for {0:C}"; }
public void Out(MessageFormat format, double d)
{
System.Console.WriteLine(format(), d);
}
}
class Discount
{
public static double Apply(DiscountRule rule, double amount)
{
return rule() * amount; // Callback
}
public static double Maximum() { return 0.50; }
public static double Average() { return 0.20; }
public static double Minimum() { return 0.10; }
public static double None() { return 0.00; }
}
class TestDelegate1
{
public static void Main()
{
DiscountRule[] rules = { // Instantiations
Discount.None,
Discount.Minimum,
Discount.Average,
Discount.Maximum,
};
// Instantiation with a static method
MessageFormat format = Message.Class;
double buy = 100.00;
Message msg = new Message();
msg.Out(format, buy); // Invocation
// Instantiation with an instance method
format = msg.Instance;
foreach (DiscountRule r in rules)
{
double saving = Discount.Apply(r, buy); // Invocation
msg.Out(format, saving); // Invocation
}
}
}
//--------------------------------------------------------------------------------------------------------
//Events:
//the delegate creates a new type
delegate void UpdateEventHandler();
class Subject
{
private int data;
public int GetData() { return data; }
public void SetData(int value) { data = value; Changed(); }
public event UpdateEventHandler Changed;
}
class Observer
{
public Observer(Subject s) { subject = s; }
public Subject GetSubject() { return subject; }
private Subject subject;
}
class HexObserver : Observer
{
public HexObserver(Subject s)
: base(s)
{
s.Changed += Update;
}
public void Update()
{
System.Console.Write("0x{0:X} ", GetSubject().GetData());
}
}
class DecObserver : Observer
{
public DecObserver(Subject s)
: base(s)
{
s.Changed += Update;
}
public void Update()
{
System.Console.Write("{0} ", GetSubject().GetData());
}
}
class TestEvent
{
public static void Main()
{
Subject s = new Subject();
//assigns a Hex observer to object s (the constructor does the += assignment)
HexObserver ho = new HexObserver(s);
//assigns a Decimal observer to object s
DecObserver co = new DecObserver(s);
for (int c; ; )
{
System.Console.Write("\nEnter a character" +
"(followed by a return, ctrl-C to exit): ");
c = System.Console.Read();
s.SetData(c);
System.Console.Read(); // Two reads to get rid of the \r\n on PC.
System.Console.Read();
}
}
}
.
//--------------------------------------------------------------------------------------------------------
//Asynchronous processing (from http://msdn.microsoft.com/en-us/library/h80ttd5f(VS.71).aspx)
using System;
using System.Runtime.Remoting.Messaging;
// Create an asynchronous delegate.
public delegate bool FactorizingAsyncDelegate (
int factorizableNum,
ref int primefactor1,
ref int primefactor2);
// Create a class that factorizers the number.
public class PrimeFactorizer
{
public bool Factorize(
int factorizableNum,
ref int primefactor1,
ref int primefactor2)
{
primefactor1 = 1;
primefactor2 = factorizableNum;
// Factorize using a low-tech approach.
for (int i=2;i<factorizableNum;i++)
{
if (0 == (factorizableNum % i))
{
primefactor1 = i;
primefactor2 = factorizableNum / i;
break;
}
}
if (1 == primefactor1 )
return false;
else
return true ;
}
}
// Class that receives a callback when the results are available.
public class ProcessFactorizedNumber
{
private int _ulNumber;
public ProcessFactorizedNumber(int number)
{
_ulNumber = number;
}
// Note that the qualifier is one-way.
[OneWayAttribute()]
public void FactorizedResults(IAsyncResult ar)
{
int factor1=0, factor2=0;
// Extract the delegate from the AsyncResult.
FactorizingAsyncDelegate fd = (FactorizingAsyncDelegate)((AsyncResult)ar).AsyncDelegate;
// Obtain the result.
fd.EndInvoke(ref factor1, ref factor2, ar);
// Output the results.
Console.WriteLine("On CallBack: Factors of {0} : {1} {2}",
_ulNumber, factor1, factor2);
}
}
// Class that shows variations of using Asynchronous
public class Simple
{
// The following demonstrates the Asynchronous Pattern using a callback.
public void FactorizeNumber1()
{
// The following is the client code.
PrimeFactorizer pf = new PrimeFactorizer();
FactorizingAsyncDelegate fd = new FactorizingAsyncDelegate (pf.Factorize);
int factorizableNum = 1000589023, temp=0;
// Create an instance of the class that is going
// to be called when the call completes.
ProcessFactorizedNumber fc = new ProcessFactorizedNumber(factorizableNum);
// Define the AsyncCallback delegate.
AsyncCallback cb = new AsyncCallback(fc.FactorizedResults);
// You can use any object as the state object.
Object state = new Object();
// Asynchronously invoke the Factorize method on pf.
IAsyncResult ar = fd.BeginInvoke(
factorizableNum,
ref temp,
ref temp,
cb,
state);
//
// Do some other useful work.
//. . .
}
// The following demonstrates the Asynchronous Pattern using a BeginInvoke, followed by waiting with a time-out.
public void FactorizeNumber2()
{
// The following is the client code.
PrimeFactorizer pf = new PrimeFactorizer();
FactorizingAsyncDelegate fd = new FactorizingAsyncDelegate (pf.Factorize);
int factorizableNum = 1000589023, temp=0;
// Create an instance of the class that is going
// to be called when the call completes.
ProcessFactorizedNumber fc = new ProcessFactorizedNumber(factorizableNum);
// Define the AsyncCallback delegate.
AsyncCallback cb =
new AsyncCallback(fc.FactorizedResults);
// You can use any object as the state object.
Object state = new Object();
// Asynchronously invoke the Factorize method on pf.
IAsyncResult ar = fd.BeginInvoke(
factorizableNum,
ref temp,
ref temp,
null,
null);
ar.AsyncWaitHandle.WaitOne(10000, false);
if (ar.IsCompleted)
{
int factor1=0, factor2=0;
// Obtain the result.
fd.EndInvoke(ref factor1, ref factor2, ar);
// Output the results.
Console.WriteLine("Sequential : Factors of {0} : {1} {2}",
factorizableNum, factor1, factor2);
}
}
public static void Main(String[] args)
{
Simple simple = new Simple();
simple.FactorizeNumber1();
simple.FactorizeNumber2();
}