The simplest explanation is that a delegates allow you to dynamically assign the "name" of a method to a variable or pass it around as a parameter ( you aren't assigning a string name, it is a reference to the method itself you are assigning to the variable).
Other code can then look in the variable, and invoke the method stored there later.
The delegate has to have a definition (like an interface), and for this you use the delegate keyword. Say we have a delegate definition somewhere that looks like this:
public delegate bool NotifyFriendsDelegate(int intensity);
This basically just says that any method (anywhere) that returns a boolean, and takes a single parameter of type int is an instance of this delegate. So the delegate definition specifies a shape, or signature, that methods have to match.
Then say we have a class like this:
public class MyCar
{
public bool GoVisitMyFriends(NotifyFriendsDelegate thingToDoWhenWeGetThere)
{
var doOurFriendsLikeUs = false;
var driving = new DrivingClass();
var didWeGetThere = driving.DoTheDrivingNowPlease();
if(didWeGetThere)
{
doOurFriendsLikeUs = thingToDoWhenWeGetThere(11);
}
return doOurFriendsLikeUs;
}
}
This class represents a fictional car, and it has a simple method that causes the car to drive to our friend's house. If the car gets to our friends house, then we will want to notify our friends that we arrived... but the car class doesn't know exactly how to notify our friends. We might play the stereo really loud, we might blow the horn, or we might use a bullhorn.
Since the GoVisitMyFriends method doesn't know how to notify our friends exactly, instead it requires that the calling code pass in a reference to some method that can do the notification part. GoVisitMyFriends doesn't care which method you give it, as long as the method is shaped just like the definition of NotifyFriendsDelegate (it has to return boolean and accept one parameter of type int).
Now lets create a simple class that uses our fictional car:
public class MyFunClass()
{
public bool NotifyFriendsByRammingTheirHouse(int howHard)
{
var rammingModule = new RammingModule();
return rammingModule.RamFriendsHouse(howHard);
}
public bool DoSomethingFun()
{
var car = new MyCar();
var areWeCool = car.GoVisitMyFriends(NotifyFriendsByRammingTheirHouse);
return areWeCool;
}
}
This class contains a method that conforms to the signature of the NotifyFriendsDelegate. It contains a method called DoSomethingFun, which creates an instance of MyCar then invokes the GoVisitMyFriends method. And it passes in the NotifyFriendsByRammingTheirHouse method so that the MyCar class will know how we want to show our love for our friends when we get there.
And that's the simplest form of delegate usage I can think of.
BTW: I've always found it useful to think of events as special variables that contain a collection of delegate methods. The event can be assigned any number (zero to infinity) of delegates, ALL of which will be called when the event is invoked. Events are just groups of delegates that can be treated as "one thing".