Posts Tagged ‘delegates

29
Dec
07

Generic Delegates

A delegate is a type and is also a class, so we can create generic classes of that, thus generic delegates. I’ll examine what good comes from that. With functional programming becoming a streamlined concept in C# 3.0, delegates come up as very important for code readability and reuse, for everyday code and not just events / threading.

Crash course into delegates:

We want to use functions like variables, pass them around and refer to them dynamically. If you’re familiar with C/C++, this is function pointers. The classic example is that of a calculator, with functions: Add, Subtract. When the user select addition, you fetch the Add function object, assign into your delegate, and invoke it. The code invoking the delegate is always there, you change behavior only by assignment.

In C#, delegates are simply types. The syntax needs getting used to – remember - its all just a declaration and nothing more. It looks like a hybrid of a variable, class, and method declaration!.

delegate <return type> <DelegateName> (arguments)

It looks like a variable because thats how you declare it.

It looks like a class because you later new it.

And, it looks like a method because the definition is similar.

so declaring one would be:

delegate int MyDelegate(string mystring, int myint)

And using it would be:

MyDelegate myd = new MyDelegate(yourfunction/otherfunction/anyfunction);

myd(“hello”, 999); //call like your original function, do you know which of the functions are called?

Notice that using delegate inference you can also do:

MyDelegate myd = yourfunction/otherfunction/anyfunction;

directly!.

yourfunction, or anyfunction would need to match the signature of MyDelegate to be assigned to its ctor.

And thats all there is to it, you can now use myd to hold any function from the set of all functions that obey that signature!.

How about the set of all functions that have the same return type, and same number of arguments (we dont care about their type)? That one is a bigger set, and it needs more generalization, this is where generics comes into play.

case study: the Action<> generic delegate.

We want to express a delegate for a function that will take something and perform action on it, without returning anything. Therefore we only need to know the type of that something which is the parameter type.

We can go ahead and write a specialization for each case:

delegate void StringAction(String param)

delegate void IntAction(int param)

delegate void BooleanAction(bool param)

delegate void FileAction(File param)

etc..

But what we can do is somewhat like function templates in C++. We use the wildcard just to express the method parameter type.

delegate void Action<T> ( T param)

So, Action<string> simply becomes:

delegate void Action(string param)

Now Action<T> conceptually represents *all* of the delegates for functions who take a single parameter and return nothing.

Anonymous Methods

As an extra bonus, we don’t really have to remember the delegate name (in the example MyDelegate) to use it. If you provide an appropriate signature, you can use an anonymous method (like anonymous inner class in Java, but easier to the fingers), where ever a delegate is expected.

myList.ForEach( delegate ( string mystring) { do stuff with mystring } );

This is an overload of the delegate keyword. The compiler will take all of the housekeeping like generating a delegate and assigning the method to it, and notice the return type would need to be inferred.

If you use lambdas everything is inferred:

myList.ForEach(mys => do stuff with mys);

If you want to be really creative, try dropping the parens after the delegate keyword. You’ll be creating a function that works with ANY signature.

.. = delegate { anything you want to do} ;

We can now use action in any function that repeatedly applies an action on an item, such as for example, a program that would read a list of URLs, download each, and extract links from each page.