Using delegates - a simple sample

A while ago Charlie Calvert did a great job explaining delegates here. Readers were asking for more samples that would demonstrate the benefits of delegates. After a lot of hard thinking (somehow it's hard to find an easy sample!) I've come up with a simple sample which will hopefully demonstrate just that. Sorry if you don't like it.

Suppose you are designing some classes that have a DisplayHelp() method:

 public void DisplayHelp()
{
    Console.WriteLine("tf get itemspec");
    Console.WriteLine(" ");
    Console.WriteLine(" Retrieves a read-only copy of a file ");
    Console.WriteLine(" from Team Foundation Server to the local workspace ");
    Console.WriteLine(" and creates folders on disk to contain it.");
}

See how Console.WriteLine is repeated every time? What if you have to output help to a file stream instead? You'll have to change all the lines of code.

Solution: you could abstract away the logic of outputting from the actual help contents and pass this logic as a parameter:

 public void DisplayHelp(Action<string> print)
{
    print("tf get itemspec");
    print(" ");
    print(" Retrieves a read-only copy of a file ");
    print(" from Team Foundation Server to the local workspace ");
    print(" and creates folders on disk to contain it.");
}

Now you can pass the output algorithm as an argument to the DisplayHelp method:

 command.DisplayHelp(Console.WriteLine);

or, for printing to a file:

 using (var writer = new StreamWriter(@"c:\help.txt"))
{
    command.DisplayHelp(writer.WriteLine);
}

From my experience, if you have a complex hierarchy with many classes, and each of them has an output method similar to DisplayHelp, this approach actually turns out quite useful. The more I learn about programming, the more I use delegates in more and more contexts.

Note: An equally flexible approach would be using yield return to return the strings, but the yield return approach doesn't compose very well.

Another note: we could actually redirect the standard output using the Console.SetOut() method, but that would defeat the whole purpose of demonstrating delegates :)

So how do we know where to use delegates? Potentially you can use delegates wherever you use an interface with a single method (such as e.g. IDisposable). Whether you actually want to do so, remains a matter of personal preference.