Saturday, January 6, 2007

Anonymous Delegates in C#

A friend asked me recently what features other than Generics I really liked in C# 2.0. I mentioned that the anonymous delegate is one of those features. So, you might ask, what is an anonymous delegate? First of all, for those of you who don't know what delegates are, they are the C# equivalent of a function pointer, sortof.

A delegate is a strongly typed method pointer, that stores both the method reference and the object reference on which the method is defined. Delegates are declared with the syntax:

[access] delegate [return type]
[delegate name] ( [param signatures] )

where [access] is an access modifier (optional) - public, private, protected, or internal, return type is the return type of methods that will be pointed to by the delegate (or void), and the other items are relatively self-explanatory.

Now. That's how a delegate "type" is declared. However, anonymous delegates aren't really delegate types - they're delegate instances. Let's say we have a delegate called BinaryIntegerOperation declared as:

public delegate int
BinaryIntegerOperation (int a, int b);

This declaration gives us a delegate type called BinaryIntegerOperation. If we want to create a delegate instance, we need to pass the name of a function with the appropriate signature to this delegate's constructor during a invocation of the new operator. Let's assume that we have a class declared as:

public class Adder {
public int Add(int x1, int x2) {
return x1 + x2;
}
}

Let's also assume that we have some instance of the Adder class, referenced by a variable called myAdder, within the context of the code we care about. The code to construct a delegate instance of BinaryIntegerOperation using the Add method of our myAdder object instance would look like:

...
BinaryIntegerOperation op
= new BinaryIntegerOperation(
myAdder.Add);
...

and the code to invoke this delegate would look like:

int result = op(value1, value2);

(just like a normal method call).

Now, let's say that instead of declaring an Adder class, we just wanted to be able to pass some simple implementation of the BinaryIntegerOperation delegate's method signature to the delegate's constructor so that we could use it in a context that needs a BinaryIntegerOperation instance. We can do the following, instead of declaring a Adder object altogether:

BinaryIntegerOperation op
= new BinaryIntegerOperation(
delegate (int a, int b) {
return a + b;
});

As you can see from this code, the code for the delegate instance is actually placed inline using the delegate keyword, along with the parameter signatures of the method. C# will automatically create a class, instance, and method for us, so we don't have to do so ourselves.

You might say, what is the advantage of this? I use this feature very extensively, often in code dealing with list filtering or searching.

Let's say you have a list of integers, and you want to determine if any of them is larger than a particular value (say 10).

Consider the code (list is List<int>)

bool bigger = false;
foreach(int item in list) {
if(item > 10) {
bigger = true;
break;
}
}

you could instead write it as:

bool bigger =
-1 != list.FindIndex(
new Predicate<int>(
delegate (int x) {
return x > 10;
}));

where, again, list is List<int>.

No comments: