7

I've previously asked a question of about Delegates does anyone have a must have scenario where I would have to use a delegate? How does this improve my C# code?

Just as many scenarios I use it in I've always seem to be able to program around it.

sleath
  • 871
  • 1
  • 13
  • 42

11 Answers11

4

Whenever you're using a Strategy Pattern or an Observer Pattern, delegates make your work much easier than using interfaces.

Yuriy Faktorovich
  • 67,283
  • 14
  • 105
  • 142
  • 2
    that's subjective. Personally I am a fan of using an interface when implementing the Strategy Patter. I think it allows for more flexibility. For instance importing behavior from a different class from another assembly. – Stan R. Oct 15 '09 at 15:57
  • 1
    @Stan: There is no reason a delegate could not point to a method from a different class in a different assembly. A delegate is not dissimilar to an interface, as just like an interface, it defines a contract. In the cases where you only need a single function call, I would say a delegate is more appealing than an interface. It has a lower barrier to implementation, and is just as easy to use (perhaps easier given lambdas.) – jrista Oct 15 '09 at 16:44
4

Nobody mentioned this, but if you are using LINQ with Lambda you use anonymous methods all the time. Which are technically still delegates.

Lets say you have a class called Person

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

And you wanted to implement a find method where you would find the person based on their FirstName

public Person Where(List<Person> list, string firstName)
{
   //find the string
   foreach(Person item in list)
      if(item.FirstName.Equals(firstName))
        return item;
}

This is a very specific search and not very dynamic, meaning if you wanted to search by LastName you would have to change this method or write a new one.

Luckily LINQ provides an extension method called Where to which you need to pass a delegate, which you can create on the fly with the help of anonymous methods.

for instance

string searchString = "Stan";
list.Where( person => person.FirstName.Equals(searchString));

but if you wanted to change to search by LastName you would simply do this

string searchString = "R";
list.Where( person => person.LastName.Equals(searchString));

This example might be not what you were looking for, but I just wanted to show that sometimes we use delegates all the time without thinking about it or realizing it.

Stan R.
  • 15,757
  • 4
  • 50
  • 58
3

Assuming you're not talking about events - of course you can program around it. The point is to make it nicer and cleaner.

protected void Sort()
{
    foreach (string key in _dBase.Keys)
    {
      Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], 
            new Comparison<Pair<string, Dictionary<string, T>>>(
        delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
        {
            if (a == null && b != null)
                return 1;
            else if (a != null && b == null)
                return -1;
            else if (a == null && b == null)
                return 0;
            else
                return a.First.CompareTo(b.First);
        }));
    }
}

Could I do that without an inline delegate? Sure. Would I have a floppy private method in my class that would only be used for this one instance? Yup.

Edit: As mentioned in the comments, you can simplify:

Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], 
   new Comparison<Pair<string, Dictionary<string, T>>>(
   delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
   {

to

Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], (a,b) =>
   {
Tom Ritter
  • 99,986
  • 30
  • 138
  • 174
  • 2
    not really a good example to show when you are stressing **nicer** and **cleaner** – Stan R. Oct 15 '09 at 15:55
  • Especially since there's no need to write 'new Comparison' since v2.0 and all the other angle bracket stuff since v3.5. Array.Sort(_dBase[key], (a, b) => { ... }); looks much better. – elder_george Oct 15 '09 at 15:59
  • The data structure is bit hairy; but there's no reason to provide context on how it's used or documented. The point was to demonstrate how an inline delegate provides encapsulation instead of cluttering a class; not focus on the data structure. – Tom Ritter Oct 15 '09 at 16:00
3

If you imagine C# without delegates, you would commonly encounter situations where you have classes or interfaces with one method. The name of that method is redundant. e.g.

public interface IGetMail
{
    Mail JustGetTheMail();
}

The interface is all about that one method. A reference to an object of that type is really no more than a reference to a single callable method. The calling code:

Mail m = getMail.JustGetTheMail();

could be abreviated to:

Mail m = getMail();

The compiler could do that as "syntactic sugar" without any ambiguity, because there's only one method you could possible call on that getMail reference.

So let's add that feature to our C# compiler. Now, when declaring these types, we could make that a little neater as well. We don't need to specify the method name when calling it, so why should we have to give the method a name in the first place?

Let's pick a standard method name, Invoke, i.e.

public interface IGetMail
{
    Mail Invoke();
}

We'll add some more syntactic sugar to allow us to write that as:

public delegate Mail GetMail();

Hey presto. We've added delegates to our C# compiler.

(Technically the CLR is also aware of delegates, and so rather than generating an interface, the C# compiler generates a special "delegate" type, which has support for asynchronous invocation, and manipulating an immutable list of delegates and treating them as a single reference; but in a basic form it could have been done with interfaces. There is a proposal to do that for Java).

We can then go further and add anonymous delegates - making them succinct to implement in a way that interfaces are not.

So to answer your question - any time where your interface has one method, it could be a delegate, and you'll be able to seriously cut down the amount of junk code you have to write.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
3

Real World Usage:

  1. Assume you have a simple user control called Checker- which comprises of just 2 checkboxes - chkA and chkB.
  2. Within the user-control you can control the check/uncheck events by implementing the respective events fro chkA and ChkB

3.Now, in a new Win Form , when you drag in Checker...and your objective is to make sure that when chkA is clicked you have to change the background color of a label...lblColorPicker.

Mind you lblColorPicker is a control that exists in the form and is not directly bound to Checker.

How will you achieve this?

Answer:

  1. First, you have to create a new event for your user control Checker.
  2. To create this new event the first thing would be to create a delegate in you user control and then use this delegate as a defining type for the new event you are writing.
  3. And then this Event has to be mapped to chkA...event in your user control.

This way you can control chkA...through the new event from any new form by referencing the event...through a delegate you just wrote.

So, much for Real-World usage!

This objective CANNOT be achieved with out writing the delegate.

Let me know if you think otherwise...or if you need more elaboration.

Shankar R10N
  • 4,926
  • 1
  • 21
  • 24
  • 1
    Poser to all: is there any way here... to avoid usage of delegates at all? – Shankar R10N Oct 15 '09 at 17:27
  • Yes, of course - delegates are, at the bottom, just classes that implement an interface with a single method and events are just a succinct implementation of the Observer pattern. To modify your example, just extend checker to accept ICheckerObserver objects and maintain a list of them. Then, in Checker's click event, it iterates its list of ICheckerObservers and calls ICheckerObserver.OnClick. – Jeff Sternal Oct 15 '09 at 18:19
2

Anonymous delegates make the code much more readable in some case (you don't have to go to another method to see code that belongs to your method:

Winforms example

class MyForm:Form{
//...
protected override void OnLoad(EventArg e){
   this.Cursor=Cursors.Wait();
   this.Enabled=false; 

   // do a long running DB operation without blocking the UI Thread
   ThreadPool.QueueUserWorkItem(state=>{

     DoLongDBOperation();

     // re enable the form
     BeginInvoke(new Action(()=>{ this.Cursor=Cursors.Default;this.Enabled=true;}));

   });
}
Florian Doyon
  • 4,146
  • 1
  • 27
  • 37
1

Delegates are an absolute must-have if you add events to your class or are doing anything asynchroneous (There are several other good reasons to have delegates). Benefits is that it is a very flexible approach.

Foxfire
  • 5,675
  • 21
  • 29
1

I think you are referring to defining custom delegates?

EventHandler has minimised the requirement for custom delegate definitions but they are still useful if you want to add additional parameters to the method signature.

Dinos
  • 411
  • 2
  • 7
1

Whenever you need to modify or change any properties of a winForms control, you need to use a delegate to pass control back to the thread the control was created on... to name just one of many examples.

Charles Bretana
  • 143,358
  • 22
  • 150
  • 216
1

One example would be a pub/sub message dispatcher. You would need to register the events with the dispatcher and then call them appropriately. This allows you to connect disparate pieces of your code quite easily. I can't think of a way to do this without using delegates

Steve
  • 11,763
  • 15
  • 70
  • 103
1

Say you have a console application that responds to different key presses:

            Action a = () => {/* Do Stuff*/};
            Action b = () => {/* Do Stuff*/};
            Action c = () => {/* Do Stuff*/};
            Action d = () => {/* Do Stuff*/};
            Action e = () => {/* Do Stuff*/};
            Action f = () => {/* Do Stuff*/};
            Action g = () => {/* Do Stuff*/};
            Action h = () => {/* Do Stuff*/};
            Action i = () => {/* Do Stuff*/};
            Action j = () => {/* Do Stuff*/};

            List<Action> actions = new List<Action>() {a,b,c,d,e,f,g,h,i,j};

            string line;

            while((line = Console.ReadKey().KeyChar) != 'q')
            {
                if(line.isBetween_0_and_9())
                {
                    actions[line.ParseInt()]();
                }
            }

You can obviously just use a bunch of Ifs but this not only easier but it's almost certainly more clear/readable.

Rodrick Chapman
  • 5,437
  • 2
  • 31
  • 32