.NET Anonymous Methods in C#

This article gives a brief demonstration of C# .NET's anonymous methods and the power and flexibility they offer developers in real world applications

Anonymous Methods

Download code for this article here.

The introduction of anonymous methods in C# 2.0 gives developers the ability to efficiently design code that makes use of delegates in callback situations. Prior to this language enhancement, a developer would have to define a separate method when needing to execute a callback using a delegate. Indeed, while not having to define a separate method to execute callbacks is certainly a nicety, that reason alone does not fully qualify the value of a new language feature such as anonymous methods. As we will see in the Web Resource Information Reader sample, the real benefit of anonymous methods can be seen in the flexibility it offers developers by allowing them to execute callbacks, synchronously or asynchronously, within its containing method code. When using anonymous methods, a developer can still reference local variables scoped for the containing method from within the anonymous method definition. Let's get started by showing how anonymous method in C# 2.0 has changed the way code can be written for callback situations.
 

Example using events

A simple example uses events. Consider the Application.ApplicationExit event that is raised when a Windows Forms application is closed. In .NET 1.1, one would have to define a method matching the System.EventHandler delegate signature and then attach that to the ApplicationExit event as such:
 

        public MainForm()
        {
            InitializeComponent();

            Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
        }

        public void Application_ApplicationExit(object sender, EventArgs args)
        {
            // Do something before the application closes.
        }

The same code can be written as an in-line, anonymous method: 

        public MainForm()
        {
            InitializeComponent();

            Application.ApplicationExit +=
                delegate(object sender, EventArgs args)
                {
                    // Do something before the application closes.
                };
        }

As you can see, the syntax in the second part of the example saves us from having to define a separate, stand-alone method. This is the most obvious benefit of anonymous methods, but aside from aesthetics, it offers little real benefit to a developer.  Now we will take a look at a more practical example that demonstrates what I consider to be a more important benefit of anonymous methods. One of the most useful implementations of this new language feature can be seen in some of the generic collection types, including the new List<T> class. List<T> is decorated with several static methods such as Exists, Find, FindAll, Remove, and RemoveAll, all of which accept a Predicate delegate (Predicate is generic delegate that has bool as its return type). 


A more useful scenario using List<T>
 
Let's say we had an application that needed to display a list of contacts with the ability for the user to seach within this list for contacts with a specific last name. We can use the FindAll method of List<T> to do this by supplying our Predicate, which points to a callback method in our class matching the required signature. As you will see, however, since the Predicate used in FindAll accepts only a single type parameter, there is no way to pass in the last name we wish to search for (unless we cache it somewhere outside the method in a member variable...ugh). Keep in mind that a call to the callback method FindContact is made for every ContactInfo in the list.
 

        public List<ContactInfo> SearchContacts(List<ContactInfo> fullList, string lastName)
        {
            return fullList.FindAll
            (
                new Predicate<ContactInfo>(FindContact)
            );
        }

        public bool FindContact(ContactInfo contact)
        {
            // No way to match last name on passed in contact info... 
        }


Again, looking at the signature of Predicate<T>, accepted by FindAll, it is quickly apparent that is not a straightforward way to implement our search. This is where an in-line method will fit in perfectly. Modified to use an anonymous method, our code now looks like this:
 

        public List<ContactInfo> SearchContacts(List<ContactInfo> fullList, string lastName)
        {
            return fullList.FindAll
            (
                delegate(ContactInfo contact)
                {
                    return contact.LastName == lastName;
                }
            );
        }

Notice two things: first, we no longer need to define a separate method for our callback operation since we are using an in-line, anonymous method; second, inside our anonymous method, we can directly reference the lastName variable, which is scoped outside our anonymous method, to compare to the LastName property of the ContactInfo instance passed in by the List<T>.FindAll method. Again, like the FindContact method in the original version, our anonymous method is called for every ContactInfo in the list.


Anonymous and asynchronous: The Web Resource Information Reader sample

The other day, I was asked by a friend to write a simple Windows Forms application that would take a list of URLs and retrieve basic headers for each, displaying the information in a DataGridView on a Form. After writing the code, I showed it to Peter and he suggested  I make an article out of it....so here I am, writing this article and finally getting to the application that started the whole idea: The Web Resource Information Reader. T-W-R-I-R....TWRIR. I know, I know...pretty cool name :)

So anyway, back to the matter at hand. The design goal of this application was simple: Download headers from the various urls as quickly and efficiently as possible and display them back to the user. Well, when dealing with web resources, one is often at the mercy of the remote server and how efficiently it can serve our request. In this case, that could mean the user has to wait a long time to see results if say, 1 out of 6 URLs takes a long time to load. This type of scenario is always perfect for a multi-threaded solution. So for TWRIR, I use the .NET ThreadPool to run each of the URL requests. To implement this, I created a static class called Reader with a static method called GetResourcesInfo which returns a DataTable containing the length, last modified, server, and status code headers for each URL. The method takes an array of urls and a second bool parameter to indicate if we should also download the page content. For this example, I will present the entire method's code first and breakdown its pieces below:
(NOTE: I have highlighted the beginning and end lines of the anonymous method in green and the key lines of code to be discussed later in yellow)

        public static DataTable GetResourcesInfo(string[] urls, bool includeContent)
        {
            // Create DataTable for results.
            DataTable table = new DataTable();
            DataColumn contentColumn = new DataColumn("Content", typeof(string));
            DataColumn urlColumn = new DataColumn("URL", typeof(string));
            DataColumn serverColumn = new DataColumn("Server", typeof(string));
            DataColumn dateLastModifiedColumn = new DataColumn("DateLastModified", typeof(string));
            DataColumn lengthColumn = new DataColumn("Length", typeof(long));
            DataColumn statusCodeColumn = new DataColumn("StatusCode", typeof(string));
            table.Columns.AddRange(new DataColumn[] {urlColumn, serverColumn, dateLastModifiedColumn, lengthColumn, statusCodeColumn, contentColumn});

            // Create dictionary for handles stored by url.
            Dictionary<string, ManualResetEvent> handles = new Dictionary<string, ManualResetEvent>();
foreach(string url in urls) { // Add new wait handle for this url to list of handles. handles.Add(url, new ManualResetEvent(false)); ThreadPool.QueueUserWorkItem( new WaitCallback( // Define in-line method to be executed asynchronously on a ThreadPool thread. delegate(object arg) { string resourceUrl = (string)arg; // passed in url. HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(resourceUrl); HttpWebResponse response = null; request.Method = includeContent? "GET" : "HEAD";\
   
                        // Add row with default values. DataRow row = table.Rows.Add(resourceUrl, "", "", 0, "", "N/A"); try { // Try to connect to url and read response from web server. response = (HttpWebResponse)request.GetResponse(); } // If an error code is returned from the server, we still want to read // the response if there is one. We can still get it from the // WebException instance. catch(WebException ex) { response = (HttpWebResponse) ex.Response; } // Read response headers we are interested in. if(response != null) { row["Length"] = response.ContentLength.ToString(); row["Server"] = response.Server; row["StatusCode"] = response.StatusCode.ToString(); row["DateLastModified"] = response.LastModified.ToString(); // If content is requested, download data stream and add to DataRow. if (includeContent) { try
                                {
                string content =
                                     new StreamReader(response.GetResponseStream(), UTF8Encoding.UTF8).ReadToEnd();
                               row[
"Content"] = content;
                               } catch (Exception ex) { row["Content"] = ex.Message; } } response.Close(); // Closes response stream. } // Notify waiting threads that the current thread's work is done. handles[resourceUrl].Set(); }), url); } // Copy handles to array and wait for all to be signaled. ManualResetEvent[] waitArray = new ManualResetEvent[handles.Count]; handles.Values.CopyTo(waitArray, 0); WaitHandle.WaitAll(waitArray); return table; }


The first thing I do in the method is create the DataTable and DataColumn objects required to store the data I will be collecting. Since I am going to use separate threads to make each URL request, I will need a way to notify the parent thread from the child thread that its work is done. To achieve this, I create a Dictionary of thread wait handles (ManualResetEvent) and add one for each URL, using the URL as the key. Then, I call ThreadPool.QueueUserWorkItem, passing in a block of code written as an in-line method matching the signature of the WaitCallback delegate used by the ThreadPool methods. Since my in-line method code is queued up to be executed asynchronously, each ThreadPool.QueueUserWorkItem in the foreach loop returns immediately and at the end of the loop we need to use the WaitHandle class to wait for all of the queued callback requests to complete. Notice both the DataTable and the Dictionary objects are defined inside the GetResourcesInfo method, but outside of the in-line method code.
(NOTE: Understanding the basics of multi-threading are not critical to this example, but it would help. A good explanation of ThreadPool usage with wait handles can be found on MSDN)

Now, let's look at the code defined in the anonymous method passed in to the ThreadPool. Using the URL passed into the anonymous method (the variable defined as "arg"), we create an HttpWebRequest object and download the headers (a good explanation of using HttpWebRequest and HttpWebResponse can be found on CodeProject). I commented the entire method as best I could to explain what each section of code does. The key lines of code, however, are where I access variables declared outside of my in-line method:

               // Add row with default values.
               DataRow row = table.Rows.Add(resourceUrl, "", "", 0, "", "N/A");
And:

               // Notify waiting threads that the current thread's work is done.
               handles[resourceUrl].Set();

Now consider what I would have had to done to implement this without using an anonymous method. One option would have been declare static fields to "cache" my DataTable and wait handle references. However, that would have been problematic, i.e. not thread-safe, if another call to GetResourcesInfo was made from somewhere else. Another solution could be to design a separate class that has instance fields for my DataTable and wait handles and defined a GetResourcesInfo method, which is probably what I would have done had this sample been written in .NET 1.1. Of course, the whole point of this article was to introduce the concept of and demonstrate the flexibility of design offered by C# anonymous methods and I hope that my humble words and illustrations have acheived that.

By Shay Shivecharan   Popularity  (20290 Views)