views:

330

answers:

9

So I read MSDN and Stack Overflow. I understand what the Action Delegate does in general but it is not clicking no matter how many examples I do. In general, the same goes for the idea of delegates. So here is my question. When you have a function like this:

public GetCustomers(Action<IEnumerable<Customer>,Exception> callBack)
{
}

What is this, and what should I pass to it?

+3  A: 

A delegate is a class that points to one or more functions. A delegate instance can be invoked, which will call the function(s) that it points to.

In your case, the GetCustomers function takes a second function as a parameter.

The second function must take two parameters of type IEnumerable<Customer> and Exception.

To call GetCustomers, you need to make a second function for it to call, then pass it a delegate containing the second function.

For example:

static void GetCustomersCallback(IEnumerable<Customer> customers, Exception ex) {
    //Do something...
}

//Elsewhere:
GetCustomers(new Action<IEnumerable<Customer>,Exception>(GetCustomersCallback));

This call creates a new delegate instance that points to the GetCustomersCallback function, and passes that delegate to the GetCustomers function. GetCustomers will presumably call the callback after the customers finish loading, and will pass the loaded customers as a parameter.
You can also leave out the delegate instantiation and pass the function directly:

GetCustomers(GetCustomersCallback);
SLaks
I don't reckon it's a class though, it's a separate sort of reference type all by itself: http://msdn.microsoft.com/en-us/library/900fyy8e(VS.71).aspx
Nick Miller
@Nick: `System.Delegate` is a class; you can see it in Reflector
SLaks
+7  A: 

it expects a function that takes IEnumerable and Exception and returns void.

void SendExceptionToCustomers(IEnumerable<Customer> customers, Exception ex) {
   foreach(var customer in customers)
      customer.SendMessage(ex.Message);
}

GetCustomers(SendExceptionToCustomers);

btw, GetCustomers seems like a terrible name for this function -- it's asking for an action, so its more like DoSomethingToCustomers

EDIT in response to comment


Ok Makes sense, So now why even bother with having a GetCustomer Function? Can't I do that same thing with your function if i Just rename it GetCustomer?

Well, what's happening here is the caller can specify some action. Suppose GetCustomers is implemented like this:

public void GetCustomers(Action<Enumerable<Customer>, Exception> handleError) {
    Customer[] customerlist =  GetCustomersFromDatabase();
    try {
        foreach(var c in customerList) 
            c.ProcessSomething()
    } catch (Exception e) {
        handleError(customerList, e);
    }
}

then you could call Getcustomers from somewhere on a commandline program, and pass it

GetCustomers((list, exception) => { 
    Console.WriteLine("Encountered error processing the following customers");
    foreach(var customer in list) Console.WriteLine(customer.Name);
    Console.WriteLine(exception.Message);
}); 

while you could call GetCustomers from a remote application, for example, and pass it

Getcustomers((list, exception) => { 
    // code that emails me the exception message and customer list
})


Also, Slak's comment suggests another reason for delegate parameter -- GetCustomers does retrieve the customers, but asynchronously. Whenever it is done retrieving the customers, it calls the function you give it with either the customerlist or an exception, if an exception occurred.

Jimmy
Agreed on the bad name.
Rob Packwood
It sounds like the callback receives the customers that were loaded (or an exception) after the customers load asynchronously.
SLaks
I would love to do something to customers most of the time especially when they're annoying.
John K
Ok Makes sense, So now why even bother with having a GetCustomer Function? Can't I do that same thing with your function if i Just rename it GetCustomer?
The `GetCustomers` function loads customers in the background, then calls the callback when it finishes and gives it the customers that were loaded.
SLaks
@Slaks, oh, that makes sense, if it passes either a customerlist or an exception to the callback. It would have to do something like that if it was an asynchronous database call.
Jimmy
A: 

You would pass it a void method that takes an IEnumerable and an Exception as parameters...

Say you have this method:

public void DoSomeStuffWithCustomers(
  IEnumerable<Customer> customers, Exception exception)
{     
}

You would call the GetCustomers method like this:

GetCustomers(DoSomeStuffWithCustomers);
Rob Packwood
+2  A: 

you can call it with a lambda

GetCustomers((cust, ex) => {
    //do something here}
);
Hueso Azul
+1  A: 

It's just an updated version of C's function pointers with the possibility of it being tied to an object instance if it's a non-static object method pointer (C++ called them method pointers when they added objects and function pointers together).

The type signature can be made generic using C#'s generic's features.

All the generics stuff is just templatizing the signature.

The name delegate is poorly chosen (unless you think of all of our apps being driven by frameworks). Because the use is not always "to delegate". Often times it's the code you have delegated some responsibility to (an iterator, say) which calls the "delegate" you previously sent in. Which is why you often see the term callback.

Callbacks have traditionally been used in frameworks for your application code to be called in the middle of a loop or when a particular event happens. It allows you to get your code to happen in the middle of other code - in fact, it's just about the only way within a thread.

Obviously, .NET event handlers are delegates being called by the framework at appropriate times, and you can accept delegates in your functions and call them appropriate to allow you to make your code somewhat generic/reusable/organized.

Cade Roux
A: 

They confused the hell out of me until I read:

  1. Andrew Troelsen's explanation of them in Pro C# 2008 and the .Net 3.5 Platform
  2. The chapter on the Observer pattern in Head First Design Patterns

That second book is about java, and doesn't mention delegates, but it explains well a problem delegates help solve: communication between classes.

Nick Miller
A: 

Refer link for details on DotNet delegates and events: http://www.codeproject.com/KB/cs/Delegate_To_Event_in_CS.aspx

Rakesh Gunijan
+1  A: 

.NET Delegates: A Bedtime Story

Patrick Steele
A: 

Simply? Function pointers

SiN