Definition and Explanation of it
Delegates are often defined as Object Oriented Function Pointers. What the heck is this definition anyway? Let us dissect what each means. In a traditional procedural language like C, a function pointer is just a memory address where to begin execution. But when it comes to OO languages a memory address isn’t sufficient. Objects have both behavior as well as data. A function call doesn’t make sense unless we can associate it with the state of the object instance. In a procedural language all the state is passed as parameters. In an OO environment some of the state could be parameters, where as some could be instance state.
So to call a function in the OO world we need
the method address
the object instance handle or the this pointer
This is why a delegate is often referred to as an object oriented function pointer. Now you know what this definition really means.
Why do we need delegates?
A delegate is required for a call back or for an event handler.
A call back is a case you provide someone with a function pointer / delegate and that someone calls you back. Assume you have cached some object (say it represents the configuration information stored in a file). Let us say the file changes and this object in cache is invalid. You need some way of reloading this object when this file changes. What you need to do is provide the framework with a function pointer / delegate and the framework will call you back when the file changes.
An event is a notification that occurs when something of concern happens. A good example of an event is a button click.
Event is sort of an anonymous broadcast in contrast to a callback which is a sort of handshake.
Still not clear, well assume you are the author of a button control. You need to call user code when the button is clicked. The user could name his method anything and this method could belong to any class. How does Microsoft know what I am going to name my class and method? A delegate encapsulates the things needed for making the call into an object. What are the things needed for making this call?
Your type details like class name, this pointer etc (_target variable)
Your method details like method signature, address etc (_methodPtr variable)
How is a delegate implemented?
(Internals, skip this if you want)
When we declare a delegate what we actually do is define a class.
public delegate void ClickEventHandler(object sender, EventArgs e);
results in the compiler generating a class like this:
public class ClickEventHandler : MultiCastDelegate
public ClickEventHandler(Object target, Int32 methodPtr);
// Method with same prototype as specified by the source code
public void virtual Invoke(object sender, EventArgs e);
// Methods allowing the callback to be called asynchronously
public virtual IAsyncResult BeginInvoke(
object sender, EventArgs e, AsyncCallback callback, Object object);
public virtual void EndInvoke(IAsyncResult result);
The actual implementations of the methods are synthesized by the runtime. The CLR-synthesized Invoke implementation for IA-32 is simply an eight-instruction shim that replaces the ‘this’ pointer in ‘ecx’ register with that of the target object reference. The shim then jmps directly to the target method address. After the jmp occurs, the target method begins execution as if it were invoked directly by the caller. In fact, because the caller’s return address is still on the stack, the target method will return directly to the caller, bypassing the delegate machinery altogether. The shim used by the Invoke method is capable of working generically because the signature of the target method is guaranteed to match that of the Invoke method exactly. All this makes delegate based invocation slightly costlier than normal method invocation.
The multicast delegate provides chaining capability to delegates. The multicast delegate class inherits from the Delegate class and adds the chaining feature to delegates. The compiler does the dirty work of translating the delegate wiring (creation) and the delegate call to a dispatch to the invoke method.
Delegate is immutable. The same scenario can be handled using interfaces too. Microsoft can define an interface and you class has to implement the interface. Once you implement the interface Microsoft can call your code using the interface. This is the approach java takes as there is no in-built language support for delegates.
An Introduction to Delegates – Jeffrey Richter
Delegates, Part 2 – Jeffrey Richter
Implementation of Events with Delegates – Jeffrey Richter
The Truth About Delegates, Microsoft Answer to Sun’s whitepater on Delegates
Hejlsberg’s interview on C# Delegates and Components
About Type-Safety of Delegates