A Beginner’s Tutorial on Basics of Delegates, Anonymous Functions and Lambda Expressions in C#

This article talks about the delegates and how to write delegate handlers using functions, anonymous functions and Lambda expressions. This article is written from a beginner’s perspective and contain very introductory material on the related topics. 

Background

There are many a times when we need one part/object of our application to do something when some other part/object has been changed. One way to achieve this is by having an object poll continuously to another object and act whenever the other objects state is changed. Now this approach is not elegant it involves too much of CPU usage. Also, there will be some time interval between 2 consecutive poll request and if the other objects state was changed during this period then we will get to know it later i.e. delayed information.

Now the way this problem is solved is called the Observer Pattern. Here the object who wants to listen to the state change can subscribe to the object whose state will be changed. If we need to put this mechanism in a C# application then we need to take care of both the aspects of this pattern. One is sending the state change from an object to the listener(all the listeners) and receiving the state change of the object.

Delegatesis the C# way of implementing the first part i.e. keeping a track of all the listeners and sending them the notification when any state is changed. Anonymousmethods and Lambda expressions come on the other side i.e. handling the response coming from a delegate

Using the code

Let us try to implement a simple application with a class called BatteryLevelto understand these topics in action. This class will keep track of the current battery level of a device. Other classes can subscribe to a delegateprovided by this class to listen to battery level change. Let us look at this class without any delegates introduced.

To implement delegates and its handlers there are mainly 4 steps involved:

  1. Declaring the delegate
  2. Creating the delegate
  3. Hooking the delegate with handler functions
  4. Invoking the delegates

Now before adding a delegate to this class lets get some basics clear. Delegates are types which we can define. The definition will declare the delegate and specify the method signature that this delegate can hold and call. Typical delegate declaration will look like:

[<em>Access Modifier</em>] delegate [<em>Return type</em>] [DELEGATE_NAME]([<em>Function arguments</em>]);

So to declare a delegate for our class, lets say we want the handler functions to return void and accept an integer value indicating the new battery level. The declaration will look like:

Delegates can hold reference to a number of methods and when a delegate is invoked, it will call all the methods one by one sequentially. C++ programmers can think of delegates as a list of type safe function pointers.

Now we have seen the first part of our 4 step process. Now if we move on to the second part i.e Creating the delegate, we simply need create a type of the delegate and assign some handler functions to it. if no handlers are associated with the delegate object it will be null. So lets create a delegate type first.

Now we have seen the second part of our 4 step process. Now if we move on to the fourth part i.e. invoking the delegate. The the typical way to call all the functions associated with this delegate would be to call the delegate like a function.

So now the BatteryLevelclass definition with the delegate will look like:

Now we have seen the invoker objects part of implementing delegates i.e. declaring, creating and invoking a delegate. Now let us see how the handing part can be written i.e. hooking the functions to the delegates and having the handler function’s body.

To hook a function to the delegate we simply need to create the delegate type with the function name passed in the constructor. We can then assign this delegate type to the delegate exposed by the class.

The above code simply creates a function and then attach that function to the delegate exposed by the class as the handler function. the function signature matches the delegate signature otherwise the code would not compile.

We are also setting the value of battery level to test the application. Whenever we call set our handler function will be invoked and it will print the message on the console.

Note: We have used += to assign the delegate because we need our function to add to the list of functions already added to this delegate. If we simply use = sign, it will wipe off the list of existing functions and have this function as the only function associated with the delegate.

So we have seen the 3rd part of our 4 step process i.e. hooking up the handler functions with the delegates. When we run the application we can see the handler function getting called via the delegate.

Anonymous functions

Anonymous functions are the functions without any function name. C# gives us the possibility of creating functions without name. But how will this function be called if it has no name. In fact there is no way to call an anonymous function via code because the name of the function is the handle to call this function.

But we have just seen that the delegates keep handles/references of all the handler functions with them. delegates don’t need the name of the function to invoke them. so the anonymous functions are useful with the delegates only.

What anonymous function does is that instead of having separate code to hook the handler to delegate and body of the handler function we can simply have the body written in place where we are hooking the function to the delegate. So if I need to achieve the above functionality using anonymous function, I simply need to write it as:

And it will produce the same result as the earlier version but it doesn’t need the programmer to write a separate function. this is very useful when the handler function has little code and using this approach gives a cleaner code compared to the earlier version.

Lambda Expressions

Newer version of C# has Lambda expression which has made the anonymous functions more or less obsolete. For the scope of this article lets understand lambda expression is one more way of creating local anonymous functions that can be used with delegates.

Note: Lambda expression has other merits over anonymous function like the can directly be assigned to expression trees but we will keep things simple in this article and will not talk about these.

A Lambda expression can be thought of as an alternative to the anonymous methods with the following syntax:

[METHOD PARAMETERS] => [METHOD BODY]

So if were to write the similar code using lambda expression we can do that in the following manner:

Note: in this above code instead of having the implicit type parameter in lambda expression, we could have specified the type in the expression too.

The result of the above code is same as the earlier versions but the code is much cleaner compared to the earlier versions(one with the handler functions and anonymous methods).

Point of Interest

In this small article we tried to look into what delegates are and how we can implement custom delegates and their handlers. Delegates have been around from quite some time and this article seems quite late or out of time. I have written this article because someone in the Codeproject Q&A section seems quite confused about the topic. This article has been written from a beginner’s perspective. I hope this has been somewhat informative.

Download sample code for this article: DelgateAnonymousLambdaSample

One thought on “A Beginner’s Tutorial on Basics of Delegates, Anonymous Functions and Lambda Expressions in C#