Advantages of using delegates?

12,396

Solution 1

When you can directly call a method, you don't need a delegate.

A delegate is useful when the code calling the method doesn't know/care what the method it's calling is -- for example, you might invoke a long-running task and pass it a delegate to a callback method that the task can use to send notifications about its status.

Here is a (very silly) code sample:

enum TaskStatus
{
   Started,
   StillProcessing,
   Finished
}

delegate void CallbackDelegate(Task t, TaskStatus status);

class Task
{
    public void Start(CallbackDelegate callback)
    {
        callback(this, TaskStatus.Started);

        // calculate PI to 1 billion digits
        for (...)
        {
            callback(this, TaskStatus.StillProcessing);
        }

        callback(this, TaskStatus.Finished);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Task t = new Task();
        t.Start(new CallbackDelegate(MyCallbackMethod));
    }

    static void MyCallbackMethod(Task t, TaskStatus status)
    {
        Console.WriteLine("The task status is {0}", status);
    }
}

As you can see, the Task class doesn't know or care that -- in this case -- the delegate is to a method that prints the status of the task to the console. The method could equally well send the status over a network connection to another computer. Etc.

Solution 2

You're an O/S, and I'm an application. I want to tell you to call one of my methods when you detect something happening. To do that, I pass you a delegate to the method of mine which I want you to call. I don't call that method of mine myself, because I want you to call it when you detect the something. You don't call my method directly because you don't know (at your compile-time) that the method exists (I wasn't even written when you were built); instead, you call whichever method is specified by the delegate which you receive at run-time.

Solution 3

Well technically, you don't have to use delegates (except when using event handlers, then it's required). You can get by without them. Really, they are just another tool in the tool box.

The first thing that comes to mind about using them is Inversion Of Control. Any time you want to control how a function behaves from outside of it, the easiest way to do it is to place a delegate as a parameter, and have it execute the delegate.

Solution 4

You're not thinking like a programmer.

The question is, Why would you call a function directly when you could call a delegate?

A famous aphorism of David Wheeler goes: All problems in computer science can be solved by another level of indirection.

I'm being a bit tongue-in-cheek. Obviously, you will call functions directly most of the time, especially within a module. But delegates are useful when a function needs to be invoked in a context where the containing object is not available (or relevant), such as event callbacks.

Solution 5

There are two places that you could use delegates in the Observer pattern. Since I am not sure which one you are referring to, I will try to answer both.

The first is to use delegates in the subject instead of a list of IObservers. This approach seems a lot cleaner at handling multicasting since you basically have

private delegate void UpdateHandler(string message);
private UpdateHandler Update;

public void Register(IObserver observer)
{
    Update+=observer.Update;
}

public void Unregister(IObserver observer)
{
    Update-=observer.Update;
}

public void Notify(string message)
{
    Update(message);
}

instead of

public Subject()
{
    observers = new List<IObserver>();
}

public void Register(IObserver observer)
{
    observers.Add(observer);
}

public void Unregister(IObserver observer)
{
    observers.Remove(observer);
}

public void Notify(string message)
{
    // call update method for every observer
    foreach (IObserver observer in observers)
    {
        observer.Update(message);
    }
}

Unless you need to do something special and require a reference to the entire IObserver object, I would think the delegates would be cleaner.

The second case is to use pass delegates instead of IObervers for example

public delegate void UpdateHandler(string message);
private UpdateHandler Update;

public void Register(UpdateHandler observerRoutine)
{
    Update+=observerRoutine;
}

public void Unregister(UpdateHandler observerRoutine)
{
    Update-=observerRoutine;
}

public void Notify(string message)
{
    Update(message);
}

With this, Observers don't need to implement an interface. You could even pass in a lambda expression. This changes in the level of control is pretty much the difference. Whether this is good or bad is up to you.

Share:
12,396
Admin
Author by

Admin

Updated on June 14, 2022

Comments

  • Admin
    Admin about 2 years

    I'm looking to implement the Observer pattern in VB.NET or C# or some other first-class .NET language. I've heard that delegates can be used for this, but can't figure out why they would be preferred over plain old interfaces implemented on observers. So,

    • Why should I use delegates instead of defining my own interfaces and passing around references to objects implementing them?
    • Why might I want to avoid using delegates, and go with good ol'-fashioned interfaces?
  • ChrisW
    ChrisW almost 14 years
    en.wikipedia.org/wiki/Indirection says, this is often deliberately mis-quoted with "abstraction layer" substituted for "level of indirection". Kevlin Henney's corollary to this is, "...except for the problem of too many layers of indirection."
  • Adam Robinson
    Adam Robinson almost 14 years
    This is more of an analogy for events, not delegates in general.
  • Cloud2010
    Cloud2010 almost 14 years
    yeah I am now somewhat getting u, but can u pls provide soem code related example, that will be better for me to understand
  • Toby
    Toby almost 14 years
    I've used variations of the Strategy pattern that worked quite well with delegates for the strategy. Or a publisher/subscriber model where I provide a subscriber class that implements 90+% of the typical subscriber functionality as a wrapper around a callback to handle the other 10-%.
  • ChrisW
    ChrisW almost 14 years
    @Cloud2010 For example, see all the places where delegates and/or events are used in the >NET framework: for example, the Control.Click Event or the List<T>.ForEach Method.
  • FrustratedWithFormsDesigner
    FrustratedWithFormsDesigner almost 14 years
    @Cloud2010: Here's an example of the atexit function (and reference to on_exit )which executes when the process exits. The function bye (in the example) is called by the OS when it detects the process is exiting. gnu.org/s/libc/manual/html_node/Cleanups-on-Exit.html
  • Matthew Vines
    Matthew Vines almost 14 years
    I guess I am taking a leap or two, but a delegate is just a reference to a method. The OP asked why you would want a reference to a method. I responded with a metaphor of a classic use of delegates (ie. events).
  • supercat
    supercat almost 14 years
    The "observer interface" method has a couple of advantages I can see: -1- given a weak reference to an observer, one can execute its "observe" method on it; there is no means in .net 2.x to keep a delegate without keeping a strong reference (or "reconstitute" a weak reference into a delegate). -2- With an observer/interface pattern, one can ask observers whether they're still "interested", and remove them if they're not. When using delegates, such removal is much harder and requires much more coordination between the event publisher and subscriber.
  • Konrad Rudolph
    Konrad Rudolph almost 14 years
    @supercat: your point 1 only partially true – you can implement your own delegate-like classes for use with weak references – this is especially important with events and supported by the custom event sytax. I’m not sure about your second point – isn’t that something that the observer can decide anyway, once it gets called? I don’t see the problem.
  • CurtainDog
    CurtainDog almost 14 years
    Wow, those links are from the history books. I do find most of the points raised on both sides quite trivial, and due simply to the acrimony between the two sides over Microsoft's then changes to the language. It basically distills down to whether saving one line of code (the method signature) is worth the addition of delegates. In my view there's no compelling reason to have them there.
  • supercat
    supercat over 13 years
    There's no good way to implement weak-event behavior without some special cooperation by the code using it. While an event handler that receives an event it's not interested in could attempt to unsubscribe, attempting to unsubscribe from within an event handler could potentially cause deadlock, depending upon how the event is implemented. I would not think it safe for a handler to assume it can unsubscribe from within a running event.