I struggle with using delegates because I know they are powerful and useful, but I don’t like the trade-off that A) not everyone is comfortable with them and B) how not-intuitive, using them typically makes the code.
With that said, I wanted to write down how to use delegates when you see those Predicate<T> argument types. For example, let’s say you have a list of Customer objects – and assume the list is populated:
List<Customer> customers = new List<Customer>();
// Assume customers gets populated
Now, if you needed to find the right customer object, based of the last name, you might do something like this:
string nameToFind = "Seder";
Customer currentCustomer = null;
foreach (Customer customer in customers)
if (customer.FirstName.Equals(nameToFind, StringComparison.InvariantCultureIgnoreCase))
currentCustomer = customer;
But you may noticed that List<T> has a couple of different "Find" functions. What’s worst, is .Find() for example will look to be declared like:
Customer Find(Predicate<Customer> match);
But what the hell is that? Well, the short answer is that you can use an anonymous delegate. An anonymous delegate is kind of like saying "I want to create a function, but I just want to use the guts of that function on the fly". I know that’s a horrible definition, but it’s the best I have, without an example. So, consider the for-each above. The code below, basically does the same thing:
currentCustomer = customers.Find(delegate(Customer customer)
return customer.FirstName.Equals(nameToFind, StringComparison.InvariantCultureIgnoreCase);
So the usage is basically that "delegate" takes the place of where you might have a function name, and the rest takes the form of a regular function. In this particular case, this code is run for each item in the collection and the first match is returned.
So as you can see, this is less code – and somewhat clear, but I’m still torn on when to push anonymous delegates – because they can be tricky and they certainly aren’t as clear as a good ol’ fashioned for-each!