Monday, August 16, 2010

Methods, Delegates, Anonymous Delegates, and Lambda Expressions

Methods, Delegates, Anonymous Delegates, and Lambda Expressions

If we have a method declared as follows:

     static Int32 SomeMethod(Int32 input)
            return input + 1;

We can explicitly call it in a way every C# programmer should be familiar with:

    Int32 y = SomeMethod(5);

Using a Delegate...

Now, we may want to wrap this call so we can execute it from somewhere else.
This is done through a delegate.

What's a delegate?

A delegate is an object instance  that "wraps" a method call (pretty much everything in the .NET framework in an object).
An easy way to think of it is as a reference to a method that we can pass around separately from the object
that "ownes" the method.  In order to "wrap" the method call, the delegate needs two things:

   1.      A reference to the instance of the object it will be calling the method on.
   2.      A reference to the method.

To create a delegate we first declare our delegate type.
We can think of this as being similar to declaring a new class:

       delegate Int32 SomeMethodDelegate(Int32 input);

And then we can use an instance of this delegate to "wrap" our method call:

Using the same method we had earlier...

    static Int32 SomeMethod(Int32 input)
            return input + 1;

Somewhere else in our code we can instantiate the delegate as follows.
(note: in the sample below, "Program" is a static class)

// f is a delegate object that "wraps" the call
SomeMethodDelegate f = new SomeMethodDelegate(Program.SomeMethod);

Now we can use our delegate instance to call the same method.

    Int32 y = f(5);

The compiler is smart enough to figure out which kind of delegate to instantiate 
so we can use a shorter syntax if we want. We are actually still very explicitly instantiating a delegate
by telling the compiler what kind of delegate we want with the declaration on the left hand side of the assignment operator.
(note: I don't need to specify the object in the following code sample because
the delegate instantiation is in the same class as "SomeMethod()".)

    // f is a delegate object that "wraps" the call
    SomeMethodDelegate f = SomeMethod;

Adding Generics in the Mix....

We may not need a bunch of explicit delegate types lying around in our project
(although sometimes it is good to have a few for more readable code) and can use generics to consolidate all delegates
with similar surface areas (the same input and output types):

    delegate TOutput GenericDelegate(TInput input);

Now we can wrap our method using our generic delegate just as before:

    // using generic delegate definition

    GenericDelegate f = SomeMethod;

    Int32 y = f(5);

Note: this GenericDelegate<>  is the same as the Func<> delegate defined in the 3.0 framework

    // using built-in Func<> generic delegate definition (3.0 framework)

    Func f = SomeMethod;

    Int32 y = f(5);

We also have the generic Action<> delegate which wraps a method with no return value and
a Predicate<> delegate which is usually used to perform tests returns a Boolean and
a Comparison<> delegate to compare two objects.

Anonymous Delegate....

We may want to have a method that does not belong to a class (which is why we call it anonymous)
and can declare it in-line using  the following syntax.  Notice how the method has no "outer shell" definition.
The "SomeMethodDelegate" object is still instantiated and points to the in-line method.

    // in-line method definition... it has no name so it is anonymous

    SomeMethodDelegate f = delegate(Int32 x) { return x + 1; };

    Int32 y = f(5);

We could use the same syntax to instantiate our anonymous delegate as well

    // in-line method definition... it has no name so it is anonymous

    Func f = delegate(Int32 x) { return x + 1; };

    Int32 y = f(5);

If you haven't done it already, it is worth taking some time and using the debugger to step
through code containing anonymous method to get a better understanding of how the execution of the code flows.


One of the ultra-cool features of anonymous methods is that they support closures which is a concept
coming out of functional programming languages.  Closures are VERY powerful and can help us keep code more concise.
When a language supports closures it basically  means that the a method body has
access to any local variable declared outside it's scope.

    String hi = "Hello World";

    Action myAction = Console.WriteLine;

    Func myStringGetter = delegate()


            // the variable "hi" is available here because

            // anonymous methods support closure

            return hi;



Lambda Expressions...

The syntax for declaring an anonymous delegate is pretty verbose (and kind of ugly). 
With the 3.5 Framework, we have a much shorter (and nicer) way to instantiate anonymous delegates using lambda expressions.
    SomeMethodDelegate f = x => { return x + 1;  };

    Int32 y = f(5);

The input parameter is the variable before the => symbol.
    x => { return x + 1;  };

The body of the method is what appear after the => symbol.

    x => { return x + 1;  };

Because the "SomeMethodDelegate" signature says we have to input a Int32 and output an Int32,
the compiler knows that our "x" variable should be an integer (see if makes more sense if you try and
match the delegate signature (below) up with our lambda expression (above).
delegate Int32 SomeMethodDelegate(Int32 input);

We can use an even shorter syntax for declaring simple anonymous methods with the lamba expression and
 leave off the brackets and the "return" keyword.  The following code uses the simpler syntax:
    // can use shorter syntax if you don't want brackets or "return" keyword

    SomeMethodDelegate f = x => x + 1;

    Int32 y = f(5);


Of course we can use lambda expressions with generic delegates as well.  The following shows the lambda expression syntax
for instantiating a generic delegate with two input parameters.  If our delegate has multiple input parameters,
we must group them in parenthesis:
    Func add = (m, n) => m + n;

    Int32 y = add(3, 4);

What Are They Good For?

Delegates are used most frequently for subscribing to events
so we'll look at how we can utilize delegates with an object that exposes an event.

Here is our dummy event raising object which could just as easily be a UI form or control.

    class Broadcast


            private event EventHandler m_somethingHappened;

            public event EventHandler SomethingHappened


                add { m_somethingHappened += value; }

                remove { m_somethingHappened -= value; }


            public void Fire()


                if (null != m_somethingHappened)

                    m_somethingHappened(this, EventArgs.Empty);



Example 1:

Let's say we instantiate a new Broadcast object and want to wire up the events using anonymous delegates:

    Broadcast bc = new Broadcast();

    bc.SomethingHappened += delegate(Object sender, EventArgs args)


            Console.WriteLine("Something Happened (anonymous method)");



Example 2:

We can also wire up our Broadcast object using a lambda expression:

    Broadcast bc = new Broadcast();

    bc.SomethingHappened += (snd, arg) => Console.WriteLine("Something Happened (Lambda)");


Example 3:

There are also many other places where delegates can be useful.
Another scenario is when we need to pass a delegate to another method for execution.
See if you can figure out what's happening in the following code.

If we have a method declared that accepts a delegate and another item defined as its input parameters
it will execute the method using the second parameter as input.

    static TOutput ExecuteSomething(Func mthd, TInput input)


            return mthd(input);


    Console.WriteLine(ExecuteSomething(g => g - 5, 20));


Post a Comment