17

I think that I conceptually understand C# delegates, however, I am struggling to find a real world example where they would be useful. Can you provide some answers detailing how C# delegates were used in real applications and what problems they enabled you to get around.

1
  • 2
    Almost every single class in the .NET framework exposes some set of events, so there you go. It is just a way to encapsulate some unit of work. For example, say you were implementing a generic binary tree structure in C. Well, the only way to order your tree would be to take as a parameter a function pointer which knew how to do the sorting. Feb 28, 2011 at 23:57

10 Answers 10

18

GUI code uses delegates to handle events, such as button clicks, window moves. Using the delegate allows you do have a function called whenever the event occurs. An example would be linking a function that saves data to a "Save" button on the interface. When the button gets clicked it is set up to execute the function that saves data. It's useful in GUI programming because your whole program could be waiting for the user to do something and you have no way of knowing what they will do first. Using delegates allows the functionality of your program to be connected to the UI in such a way that the user can do things in any way they want.

1
15

Linq uses the Func<T> and Action<T> delegates all over the place as parameters.

These allow you to use lambda expressions as parameters and define the action to be taken as part of the parameter list.

12

Virtually anything using the Observer Pattern would likely implement delegates.

Read the description and you'll probably imagine some scenarios where you would use them. GUI event handling is a common example.

1
  • +1, The strategy pattern is really where delegates shine, ie, you have some class where some method does something, but you want the something to be interchangeable and without direct dependency, ergo delegates. Note that events kinda fill the same need as delegates, the difference is that you use delegates when you need to react on some return value, whereas you just fire events and whatever will be will be.
    – Homde
    Feb 28, 2011 at 23:42
9

Delegates are bloody useful in asynchronous programming.

You have a class which does stuff asynchronously and has a callback. You can have the delegate method invoked upon callback - and your class implementation will do the logic described in your delegate method.

9

Delegates are particularly useful as a solution for the hole in the middle pattern. Essentially, there are a lot of cases where you want to wrap a unique set of instructions inside of a common bunch of instructions. It's particularly difficult if the instructions before and after the unique bit need to share state. With delegates, you can just pass a delegate into a function. The function executes the before bit, executes the delegate, then executes the after bit.

5

In the "old days" of non-OOP languages like Fortran and C, it was incredibly useful to be able to have a subroutine receive an argument which was a pointer to a function. For example, the qsort function works with a user-provided comparison function. There are numerous subroutines for solving ordinary differential equations, or for optimizing functions, and they all take function pointers as arguments.

In windowing systems, all kinds of callbacks follow the same pattern.

In Lisp, even in the early days, there was something called a "functional argument" or FUNARG, which was not only a function, but it also contained a storage context where it could remember and interact with part of the outside world.

This same need exists in OOP languages, except when you pass the address of a function you also have to pass the address of the object the function is a method of. That's two things you have to pass. So a delegate is just that, and allows that good old pattern to still be used.

3

Here is a simple example that shows how useful delegates can be at creating simple code that follows the DRY principle. It also allows you to keep code extremely close to where it is needed.

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

Here is a real world example of the advantage that delegates provide.

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}
2

My first encounter with delegates was checking for a program update (windows forms C# 3.5) by downloading a file from my website, but to avoid the update checking locking the whole program I used a delegate and a thread to do it asynchronously.

1

I've seen interesting implementations of the Strategy pattern that uses delegates effectively. (ie the strategy is a delegate)

The one I was looking at was for pathfinding where the algorithm to find the path was a delegate that could be (re)assigned to at runtime so that different algorithms could be used (BFS vs A* etc.)

1

Many of the classic GoF patterns can be implemented with delegates: For example, Command pattern, Visitor pattern, Strategy pattern, Factory pattern and Observer pattern can often be implemented with a simple delegate. Sometimes, a class is better (e.g. when a command needs a name or a strategy object needs to be serialized) but in most cases, using Action<...> or Func<...> is much more elegant than creating a dedicated one-method interface.

Not the answer you're looking for? Browse other questions tagged or ask your own question.