Delegates

Description

A Delegate is an object that knows how to call a method (or group of methods).
A Delegate is a reference or pointer to a function.
For designing extensible and flexible applications (eg frameworks).

public delegate void PhotoFilterHandler(Photo photo);

public void Process(string path, PhotoFilterHandler filterHandler)
{
    var photo = Photo.Load(path);
    filterHandler(photo);
    photo.Save();
}


When defining a delegate you have to supply the signature of the method that this delegate will be calling.
An instance of the delegate can hold a pointer to any function or group of functions with the specified signature. (void and parameter of type photo).
Developers using this framework can apply their own filters, so you do not have to re-compile your framework for other developers to use or extend it.

EC Types

You create instances of your PhotoProcessor and PhotoFilters classes.
Using your delegate that you defined you can add filters that were defined in your own framework, but developers can also add their own (in the case of RemoveRedEyeFilter) as long as they comply with the specified signature of your delegate.

In .NET we have 2 delegates that are generic: Action and Func.
This gives you the ability to use these generic delegates, rather that creating your own.

Action
System.Action can be normal or generic.
The generic System.Action is overloaded with 16 different parameters.

System.Action<>

Func
Difference betweeen Func and Action, is that Func points to a method that returns a value, and Action points to a method that returns void.

System.Func<>

Rather that defining your own delegate you can use the .NET generic delegates:

public delegate void PhotoFilterHandler(Photo photo); //falls away

public void Process(string path, PhotoFilterHandler filterHandler)
{
    var photo = Photo.Load(path);
    filterHandler(photo);
    photo.Save();
}

becomes

public void Process(string path, Action<Photo> filterHandler)
{
    var photo = Photo.Load(path);
    filterHandler(photo);
    photo.Save();
}
//in your Main class
PhotoPorcessor.PhotoFilterHandler filterHandler = filters.ApplyBrightness;
//change to
Action<Photo> filterHandler = filters.ApplyBrightness;
                                    
                                    
Interface or Delegates?

Use a delegate when:
- An eventing design pattern is used. - The caller doesn't need to access other properties or methods on the object implementing the method.