A delegate is a reference/pointer to a function or set of functions, allowing you to invoke methods coming from another object.
Delegates are most useful when you want to make your code extensible and flexible.
For example, suppose you are building a photo processing library. Instead of defining every process you can apply to a photo (resize, increase contrast, etc.), you can use a delegate where the user provides the processes at runtime.
This approach saves you time because you don't have to add new processes to your code and recompile everything. Instead, the user can define the processes themselves and provide them to your processor.
Similar to interfaces, delegates just accept a signature for your method(s).
// Defining a delegatepublicclassPhotoProcessor{ // Signature: return type of void, parameter of PhotopublicdelegatevoidPhotoFilterHandler(Photo photo);publicvoidProcess(string path,PhotoFilterHandler filterHandler){var photo =Photo.Load(path); // Old approach: // var filters = new PhotoFilters(); // filters.ApplyBrightness(photo); // filters.Resize(photo); // New approach:filterHandler(photo);photo.Save();}}// Using a delegatevar processor =newPhotoProcessor();var filters =newPhotoFilters();PhotoProcessor.PhotoFilterHandler filterHandler =filters.ApplyBrightness;filterHandler +=filters.Resize;// adding extra methodsprocessor.Process("photo.jpg", filterHandler);
Now if the user wants to add their own custom process like RemoveRedEye, they can just tack it onto filterHandler.
How Delegates Work Under the Hood
Behind the scenes, a delegate is just syntactic sugar for instantiating the System.Delegate class. And when you apply multiple methods to a delegate, it just uses the System.MulticastDelegate class.
Action and Func
C# provides you with built-in delegates, so you don't have to create your own custom delegates. These are Action and Func.
Use Action when the functions you give your delegate will always return void. Use Func when they will actually return something.
Note: These classes are generic classes. Every type parameter you pass matches the parameters of the function your delegate expects. For Func, the last parameter is always the return type.
Here's a refactor of the previous code to use Action instead:
Comparison to Interfaces
In practice, interfaces can serve the same benefits as delegates. So when do you use one over the other?
This doesn't make sense to me now, but here are the situations where delegates are preferred according to the MSDN docs:
public class PhotoProcessor
{
public void Process(string path, Action<Photo> filterHandler)
{
var photo = Photo.Load(path);
filterHandler(photo);
photo.Save();
}
}