Gambolling with Delegates   1 comment

In my previous post I explained the concept and basics of Delegates. I’ll assume that there is an understanding of Lambda Expressions. The following content’s interest is close to just academic but, understanding it is key to really take advantage of Delegates and wonders a good implementation provides.


Simple Start

Let’s start with this simple delegate implementation:

delegate void StringVoidDelegate(string input);

As I exposed in my previous post, this defines a method signature where a string is received as a parameter and there is no return.

Since I’m in a Console Application I’ll implement some helpers to understand what is going on using the delegate just implemented:

static int CallCount = 0;
static StringVoidDelegate CWL = input => Console.WriteLine(++CallCount + " " + input);


A simple usage of this method can be:

CWL("Calling Elvis");

With output:

1 Calling Elvis


Generic Delegate

Like any other generic capable object in .Net, delegates receive a type generically on implementation. Something like so:

delegate string ToString<T>(T obj);


If, for instance, we have a Person class like this:

class Person
    public string Name { get; set; }
    public DateTime Birthday { get; set; }


We can have a method compliant with ToString delegate signature like so:

ToString<Person> personToString = person => person.Name;


Which can be used like so:

ToString<Person> personToString = person => person.Name;
var jCleese = new Person { Name = "John Cleese", Birthday = new DateTime(1939, 10, 27) };

With output:

1 John Cleese


Stacking Delegates

Since calling a method with the assurance of its signature is so ‘OK’ we can easily stack delegates to be run consecutively, provided that the signature is the same. Same signature means all the delegates reference to de same implementation; delegates with same input and output type signatures but different implementation won’t be interoperable. Stacking and unstacking delegates is done using arithmetic ‘+’ and ‘–’ operators.

Adding adds the delegate on the right hand to the list of methods that will be called.

StringVoidDelegate Echo = input => CWL("Echo..." + input);
Echo += CWL;

With output:

1 Echo...John Cleese
2 John Cleese

So CWL will be run consequently after Echo with the same parameter.

Removing removes the last call to that method on the ‘stack’ if there is any. Say we have this parameter less delegate:

delegate void ParameterlessVoidDelegate();


This sequence:

ParameterlessVoidDelegate writeOne = () => CWL("One");
ParameterlessVoidDelegate writeTwo = () => CWL("Two");
ParameterlessVoidDelegate writeThree = () => CWL("Three");
ParameterlessVoidDelegate writeA = () => CWL("A");

ParameterlessVoidDelegate write = writeOne + writeA + writeTwo + writeA + (() => CWL("Four"));
write -= writeA;
write -= writeA;
write -= writeA;

Would have this output:

1 One
2 A
3 Two
4 A
5 Four
7 One
8 A
9 Two
10 Four
12 One
13 Two
14 Four
16 One
17 Two
18 Four


Composing results

When  adding delegates with a return object, all methods are ran from left to right but only the last return is accounted for, all others are discarded.

Let’s take this signature:

delegate int IntToIntDelegate(int value);


The following code:

IntToIntDelegate baseAddingDelegate = value =>
        return value;

IntToIntDelegate AddOne = value => baseAddingDelegate(value + 1);
IntToIntDelegate AddTwo = value => baseAddingDelegate(value + 2);

var addAll = AddOne + AddTwo + (value => baseAddingDelegate(value + 3));

(baseAddingDelegate is just a wrapper to shorten the code)

The output is this:

1 2
2 3
3 4
4 4


If the intension is to have the result of the application of all methods the implementation would have to look like so:

IntToIntDelegate AddOne = value => baseAddingDelegate(value + 1);
IntToIntDelegate AddTwo = value => baseAddingDelegate(value + 2);
IntToIntDelegate AddThree = value => baseAddingDelegate(value + 3);
IntToIntDelegate progressiveSum = value => AddOne(AddTwo(AddThree(value)));

And the result:

1 4
2 6
3 7
4 7


In Event Handling

Using delegates you can easily propagate method calling without having to reference methods in each others. For instance, having this methods:

RoutedEventHandler DoOneThing = new RoutedEventHandler((s, e) => { });
void ButtonHandler(object s, EventArgs args) { }
void DoAnotherThing() { }


This code is very OK and might be very useful:

button.Click += DoOneThing;
DoOneThing += ButtonHandler;
button.Click += (s, e) => DoAnotherThing();


.Net Action and Function

Just a quick note to say that our .Net Framework friends, since .Net 2.0, were kind enough to provide some common delegate implementation and, using generics, a short way to request for a certain signature.

Their implementation is as simple as this.



public delegate void Action();

public delegate void Action<T>(T obj);

public delegate void Action<T1, T2>(T1 arg1, T2 arg2);

public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);



That can be used like so:

var a = new Action<string, int, string>((s1, i, s2) => { CWL(s1); CWL(i.ToString()); CWL(s2); });
a("One", 2, "Three");

With this output:

1 One
2 2
3 Three



Is the same as Action but, at least, one generic type must be provide to serve as the return type. Something like so:

var f = new Func<int>(() => 3);


1 3




Delegates that can help you simplify and encapsulate your code in an error safe way. The sky is the limit. I use them all the time to wrap generic asynchronous call handlings and stuff like that.

That’s all…hope it’s useful.


Posted 2011/02/08 by Bigsby in General

Tagged with , , , ,

One response to “Gambolling with Delegates

Subscribe to comments with RSS.

  1. Pingback: Once upon a Delegate « Bigsby Spot

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: