In programming, you are often faced with situations where you need to execute a particular action, but you don’t know in advance which method, or even which object, you’ll want to call upon to execute that action. For example, a button might know that it must notify some object when it is pushed, but it might not know which object or objects need to be notified. Rather than wiring the button to a particular object, you will connect the button to a delegate and then resolve that delegate to a particular method when the program executes.
Today’s Graphical User Interface (GUI) programming model requires an approach, known as event-driven programming. A modern program presents the user interface and waits for the user to take an action. The user might take many different actions, such as choosing among menu selections, pushing buttons, updating text fields, clicking icons, and so forth. Each action causes an event to be raised. Other events can be raised without direct user action, such as events that correspond to timer ticks of the internal clock, email being received, file-copy operations completing, etc.
An event is the encapsulation of the idea that “something happened” to which the program must respond. Events and delegates are tightly coupled concepts because flexible event handling requires that the response to the event be dispatched to the appropriate event handler. An event handler is typically implemented in C# as a delegate.
Delegates are also used as callbacks so that one class can say to another “do this work and when you’re done, let me know.” Delegates can also be used to specify methods that will only become known at runtime. Technically, a delegate is a reference type used to encapsulate a method with a specific signature and return type. You can encapsulate any matching method in that delegate. (In C++ and many other languages, you can accomplish this requirement with function pointers and pointers to member functions. Unlike function pointers, delegates are object-oriented and type-safe.)
A delegate is created with the delegate keyword, followed by a return type and the signature of the methods that can be delegated to it, as in the following:
public delegate int WhichIsFirst(object obj1, object obj2);
This declaration defines a delegate named WhichIsFirst which will encapsulate any method that takes two objects as parameters and that returns an int.
Once the delegate is defined, you can encapsulate a member method with that delegate by instantiating the delegate, passing in a method that matches the return type and signature.