tags:

views:

589

answers:

9

I understand how delegates and events work. I can also imagine some common scenarios where we should implement events, but I’m having harder times understanding in what situations should delegates be used.

thanx

REPLYING TO USER KVB'S POST:

a)

You can basically use delegates wherever you would otherwise use a one-method interface.

I think I somewhat understand the following:

  • Class C could define method C.M, which would take as an argument an interface IM. This interface would define a method IM.A and thus anyone wanting to call C.M would need to implement this interface.

  • Alternatively, method C.M could take ( instead of an interface IM ) as an argument a delegate D with the same signature as method IM.A.

But what I don’t understand is why can’t C.M also use as its parameter a delegate D even if our interface IM defines several other methods besides method A? Thus, the other methods of class C could require as their argument an interface IM, but C.M could instead require a delegate D ( assuming C.M only needs to call method A and not any of the other methods defined within IM ) ?

b)

var list = new List<int>(new[] { 1, 2, 3 });
var item = list.Find(i => i % 2 == 0);
  • Is the above code an example of what user jpbochi calls ( see hers/his post in this thread ) dependency injection?

  • I assume the above code couldn’t be implemented using events instead of “pure” delegates?

+6  A: 

When you want to provide a function, that will be executed on some event. You give to the event's Event handler a delegate of a function that is about to be executed. They are great when you do event driven programming.

Also when you have functions that have functions as arguments (LINQ expressions, predicates, map-functions, aggregate functions, etc). This functions are generally called higher level functions.

In addition you can wrap some functionality, when the caller has no need access other properties, methods, or interfaces on the object implementing the method. In this case it replaces inheritance, somehow.

anthares
+2  A: 

asynchronous callbacks are another good example

Steven A. Lowe
+1  A: 

Delegates are used to pass comparison functions to generic sort routines; delegates may be used to implement the Strategy Pattern; and delegates are used to invoke asynchronous methods, among other uses.

Edited to add:

This type of comparison between delegates and events doesn't really make any sense, at a certain level. It is like asking why we would need integers when we could mark fields as "public".

An event in C# is nothing more than an access restriction on a field of a delegate type. It says, basically, that another class or object may access the field for additions and removals, but may not inspect the contents of the field or make wholesales changes to the value of the field. But the type of the event is always a delegate, and delegates have many uses that do not require the access restrictions that the event mechanism supplies.

Jeffrey L Whitledge
"...to pass comparison functions to generic sort routines" Wouldn't in this scenario interfaces be more appropriate? "...delegates are used to invoke asynchronous methods" Don't we usually use events for invoking asynchronous methods?
AspOnMyNet
An interface is appropriate for sorting if the ordering of the objects never changes, such as with numbers. A comparison function is more appropriate if a variety of sort orders needs to be supported, such as those that require multiple fields in various combinations.
Jeffrey L Whitledge
The `BeginInvoke` family of methods take delegates, not events.
Jeffrey L Whitledge
“The BeginInvoke family of methods take delegates, not events” Ah, I haven’t yet covered threads and asynchronous method calls, I just made an assumption that events could be used there too. Sorry about that
AspOnMyNet
"An interface is appropriate for sorting if the ordering of the objects never changes, such as with numbers. A comparison function is more appropriate if a variety of sort orders needs to be supported, such as those that require multiple fields in various combinations" Why couldn't we achieve that by using an interface defining several methods, where each method would be used for different sorting algorithm? Because then user that is passing an interface (as an argument) to the sorting routine would have no way of specifying which of the interface's methods the sorting routine should invoke?
AspOnMyNet
There is no limit to the number of ways that specifying a sort order could be done, including the use of an interface with separate concrete classes defined for each ordering, etc. (In fact, the SortedDictionary<TKey,TValue> class does exactly that.) But I can think of no method, within the context of the C# programming language, that would be as simple, clear, and flexible as passing a delegate. (Which is what some overloads of Array.Sort() accept.) This is even more true now that lambda expression syntax is available.
Jeffrey L Whitledge
thanx for helping me out cheers
AspOnMyNet
+3  A: 

Implementing callbacks and event listeners.

For example if you have a function that does a remote request (e.g. retrieve a list of your Facebook friends), then you could pass a delegate as final parameter to that function and have it executed once the server response has been received.

StackedCrooked
"For example if you have a function that does a remote request..." Wouldn't event be more appropriate?
AspOnMyNet
@AspOnMyNet - It heavily depends, if you have an object to attach the event to maybe, but what if it is abstracted down to a static method call? Unless you assume only one caller at a time, you have to use delegates to ensure the right method is called upon completion.
Guvante
@AspOnMyNet: Even if you use an event, you're going to have to attach a delegate to that event.
R. Bemrose
"It heavily depends, if you have an object to attach the event to maybe, but what if it is abstracted down to a static method call? Unless you assume only one caller at a time, you have to use delegates to ensure the right method is called upon completion."I don’t understand your arguments. Namely, why would static method call represent a problem to an event and why would delegate ( and not an event ) be needed to ensure the right method is called ( BTW – I do understand that events use delegates under the hood )?
AspOnMyNet
+4  A: 

In my point of view, delegates are the simplest means of dependency injection. When a component receives a delegate (either in an event or in a regular method) it is allowing another component to inject behavior to it.

jpbochi
I know that the term "dependency injection" was invented before delegates, but that does not invalidate the idea.
jpbochi
@jpbochi: actually delegates are just first class functions (Scheme and Lisp had them 35+ years ago) which are decades older than Fowler's 2004 Dependency Injection paper. Delegates in "modern" languages like C# lagged functional programming languages by decades; when MS finally added delegates it only seemed "new" because it was new to the mainstream OOP crowd.
Jared Updike
+1  A: 

I use delegates to keep my objects and class libraries loosely coupled.

For example:

  • I have two controls TabControlA and TabControlB on MainForm. Their code resides in separate libraries which are dependencies of MainForm.

  • TabControlA has a public SetShowMessage method that sets a private member called ShowMessage to any delegate (of type Action<string>, say).

  • When MainForm loads, it can get things setup by calling TabControlA.SetShowMessage(TabControlB.PrettyShowingFunction) to wire up (just this part of) TabControlB to (just that part of) TabControlA.

  • Now internally, TabControlA can check if ShowMessage is non-null and call ShowMessage("Hurray, a message that will be displayed on TabControlB!") and now TabControlB.PrettyShowingFunction gets called, allowing TabControlA to communicate with TabControlB, which can display this message.

  • This could be extended to allow TabControlC to do the same thing and show messages on TabControlB, etc.

I didn't know what this was called, but I think it's the the Mediator Pattern. Using Mediator objects you can bundle even more delegates together, for example a progress meter and status label on MainForm, which any control can update.

Jared Updike
Could you explain why wouldn’t in the example you’ve provided implementing an event (instead of just a delegate) made more sense?
AspOnMyNet
Great question. I hadn't thought of that. Guvante's comment on the original question ("Actually you can always replace delegates with events....") seems to sum it up. I find delegates to be cleaner for most simple things than creating a full event to package up the same info.
Jared Updike
+1  A: 

I like delegates and events (they go hand in hand) for separation of concern (SOC).

What is a delegate? Simply put, a delegate is a type safe method signature. Events basically store a reference to a collection of methods... Events and delegates provide a way to provide out-of-context change notifications to multiple consumers...

Publishers call events and subscribers receive notifications.

How does this work? Here's a quick example.

Let's say your code needs to valid input before processing an order. In a procedural approach, your code (controller) might trigger the 'order' method. Order then validates and then submits or rejects...

In a publisher/subscriber approach, you might have the following events OrderSubmitted, OrderValidated and OrderRejected. Those would be your publishers. You then have a few subscribers, ValidateOrder, CommitOrder and RejectOrder... ValidateOrder would subscribe to OrderSubmitted, CommitOrder subscribes to OrderValidated and finally RejectOrder subscribes to OrderRejected.

As a parameter to your events, you pass in the order. The series of events would then be...

You controller receives an order. The code assumes event null checking is taking place...

void Init()
{
    ValidateOrder += SomeValidateMethod;
    CommitOrder += SomeCommitMethod;
    RejectOrder += SomeRejectMethod;
}

void OrderReceived(Order o)
{
  OrderEventArgs OEA = new OrderEventArgs(o);

  ValidateOrder(this, OEA);

  if (OEA.OrderIsValid)
      CommitOrder(this, OEA);
  else
      RejectOrder(this, OEA);
}

Just like that, we've got some events. Now, why are we using events/delegates? Let's say the code for rejecting the order updates the database, no problem. Someone says, let's email the client when an order is rejected. Do you need to refactor SomeRejectMethod? No, you can simply create a new method EmailOrderRejected and add it as a subscriber to the RejectOrder event.

This is a very small example, but it really helps when using an event broker for a system as a whole. It helps to decouple dependencies between methods...

I'll try to follow up with some links later, good luck.

Ben
+3  A: 

You can basically use delegates wherever you would otherwise use a one-method interface. While this isn't always appropriate, often readability is greatly improved by using delegates instead of interfaces because logic is kept closer to where it is being used. For instance, which of these examples is easier to understand and check for correctness?

var list = new List<int>(new[] { 1, 2, 3 });
var item = list.Find(i => i % 2 == 0);

As opposed to:

var list = new List<int>(new[] { 1, 2, 3 });
list.Find(new DivisibleBy2Finder());

// Somewhere far away
private class DivisibleBy2Finder : IFinder<int> {
    public bool Matches(int i) {
        return i % 2 == 0;
    }
}

UPDATE

Let me expand on my answer a bit. Conceptually, delegates are very similar to one-method interfaces with special syntax for invoking the method without using its name (that is, given a delegate D, you can call its method via the syntax D()). There are two other things that make delegates more interesting than one-method interfaces:

  1. You can construct a delegate from a method group. For instance, you can create an Action<string> delegate like this: Action<string> action = new Action<string>(Console.WriteLine);. This creates a delegate that will print its argument to the console when a string is passed to it. Although this allows you to effectively pass methods around, those methods must already have been defined on some class.
  2. You can create an anonymous delegate. To me, this is the key reason that delegates are particularly useful in C#. Some other languages use different constructs to encapsulate a bit of logic at its point of use (e.g. Java has anonymous classes). C# doesn't have anonymous classes, so if you want to create a bit of freestanding logic that can be passed into another method, using an anonymous delegate (or multiple anonymous delegates) is often the best approach in C#. This is what I was trying to illustrate with my example in my original post.

The relationship between events and delegates is a bit tricky. Although it is true that events are implemented in terms of delegates, I'm not sure that is the best way to think about them. Delegates, like instances of other types, can be used in many different contexts; they can be members of a class, they can be passed into methods or returned from methods, they can be stored in local variables within a method, etc. Events, on the other hand, are special members of a class that support the following operations:

  1. Delegates can be added to or removed from the event. These delegates will be called when the event is fired/invoked.
  2. Only within the context of the class where the event is declared, the event can be treated as a standard delegate, meaning that it can be invoked and its invocation list can be inspected/manipulated.

Thus, events are frequently exposed on classes to allow other components to register callbacks, which will be invoked from within the event's class when needed. However, delegates can be used in a much wider variety of situations. Within the Base Class Library, for instance, they are frequently used as arguments to methods to perform generic operations on collections.

Hope that helps to clarify things a bit.

kvb
Hi, in case you find the time, would it be possible to offer me some additional help on the subject? Namely, I’ve edited my initial post in a response to your post
AspOnMyNet
@AspOnMyNet - I've expanded my answer a bit; see if that helps. It doesn't exactly address your revised questions, but hopefully it will clear some things up nonetheless.
kvb
+1 for the code comparison, but I don't really like the delegates-as-one-method-interface terminology. It's a very OOP-centered description, and as you point out, it doesn't capture all of it. I think it's more useful to think of delegate instances as first class functions, which enable functional programming techniques.
Isaac Cambron
@Isaac - You're right, there is a whole spectrum of ways to view the issue. On the one hand, a delegate is basically just an interface with a nameless method; on the other hand, an interface is just a set of named functions. Either view can be described in terms of the other, and which view is more helpful in any particular case probably depends on both the problem and the programmer. Given the nature of the original question, I thought that describing things from the OO perspective might give the poster more insight, though I often find the FP angle more useful myself.
kvb
“delegate instances as first class functions, which enable functional programming techniques” Uhm, I’m not exactly sure what you mean with the above. What is a FIRST class function and what exactly do you mean by functional programming techniques?
AspOnMyNet
“It doesn't exactly address your revised questions” I assume reason being that I was totally off with my updated question?
AspOnMyNet
@AspOnMyNet - Roughly speaking, in a language which supports "first-class functions", functions can be treated just like normal values (that is, they can be passed into other functions, stored in variables, returned from functions, etc.). Languages have varying support for this (e.g. in C# delegates can be seen as an implementation of first class functions, while Java does not currently support anything along these lines). See Wikipedia for more details.
kvb
@AspOnMyNet - Wikipedia also has a decent article on functional programming (although it is a fuzzy term which different people use differently). In short, functional programming takes advantage of first-class functions to enable general, "higher-order" operations. As one example, using functional programming it's easy to represent the concept of generating one list from another by "mapping" each item individually; the "map" function takes a list and a mapping function as arguments and returns the new list.
kvb
@AspOnMyNet - As to your last question, the reason I didn't exactly address your questions was that I wasn't completely sure what you were asking in part a), and also that I didn't want to speak for jpbochi in responding to part b). I hope that my expanded answer addressed the basic ideas underlying your specific questions, though.
kvb
thank you all for your help
AspOnMyNet
+1  A: 

One thing I haven't seen mentioned yet is that delegates make it easy to store methods in data structures. For instance, it's not uncommon for me to find something like this in a functional requirement:

Update all of the relevant sentence records for this charge by setting their status date to the event date. If the charge is disposed with a diversion referral, the relevant sentences are those with a sentence type of "DV", "DCV", or "DVS". If the charge is disposed with a deferred entry of judgment, the relevant sentences are those with a sentence type of "DEJ". Ignore all other charges and sentences.

One way to solve this would be to build a class for sentences and a class for charges and populate them from the data set, and then stick all of the logic above into methods. Another way would be to build a nice big set of nested conditionals.

A third way, which is more in keeping with Steve McConnell's observation that it's easier to debug data than code, is to define a lookup table that contains predicates to use for testing sentence rows:

private static readonly HashSet<string> DiversionTypes = 
    new HashSet() { "DV", "DCV", "DVS" };
private bool SentenceIsDiversion(DataRow r) { return (DiversionTypes.Contains(r.Field<string>("Type"))); }

private bool SentenceIsDEJ(DataRow r) { return r.Field<string>("Type") == "DEJ"; }

// Map charge disposition codes for diversion and DEJ to predicates that
// test sentence rows for relevance.  Only sentences for charges whose disposition
// code is in this map and who are described by the related predicate should be
// updated.
private static readonly Dictionary<string, Func<DataRow, bool>> DispoToPredicateMap =
    new Dictionary<string, Func<DataRow, bool>>
{
   { "411211", SentenceIsDiversion },
   { "411212", SentenceIsDiversion },
   { "411213", SentenceIsDEJ },
   { "411214", SentenceIsDEJ },
}

Which makes the update logic look like this:

string disposition = chargeRow.Field<string>("Disposition");
if (DispoToPredicateMap.ContainsKey(disposition))
{
    foreach (DataRow sentenceRow in chargeRow.GetChildRows("FK_Sentence_Charge"))
    {
       if (DispoToPredicateMap[disposition](sentenceRow))
       {
          sentenceRow.SetField("StatusDate", eventDate);
       }
    }
}

Of the three approaches, this is the hardest to come up with in the first place (or to understand, if you aren't familiar with the technique). But it's much easier to write unit tests that cover 100% of the code, and it's easy to update when the triggering conditions change, too.

Robert Rossney