Freigeben über


Delegates, Events, and Lambda Expressions

This chapter is excerpted from C# 3.0 Cookbook, Third Edition: More than 250 solutions for C# 3.0 programmers by Jay Hilyard, Stephen Teilhet, published by O'Reilly Media

C# 3.0 Cookbook, Third Edition

Logo

Buy Now

Introduction

A delegate is an object which represents a method and, optionally, the "this" object associated with that method. When the delegate is invoked, the corresponding method is invoked. Delegates contain all that is needed to allow a method, with a specific signature and return type, to be invoked by your code. A delegate can be passed to methods, and a reference to it can be stored in a structure or class. A delegate is used when, at design time, you do not know which method you need to call, and the information to determine this is available only at runtime.

Another scenario, is when the code calling a method is being developed independently of the code that will supply the method to be called. The classic example is a Windows Forms control. If you create a control, you are unlikely to know what method should be called in the application when the control raises an event, so you must provide a delegate to allow the application to hook up a handler to the event. When other developers use your control, they will typically decide when they are adding the control (through the designer or programmatically) and which method should be called to handle the event published by the control. (For example, it's common to connect a Button's click handler to a delegate at design time.)

Events are a specialized delegate type primarily used for message or notification passing. Events can only be invoked from the type they are published from and are typically based on the EventHandler delegate with an object representing the sender of the event and a System.EventArgs derived class holding data about the event.

Anonymous methods are expressions that can be converted to delegates. They are a feature of the C# compiler and not a CLR type. An anonymous method is ultimately created as a delegate instance by the compiler, but the syntax for declaring an anonymous method can be more concise than declaring a regular delegate. Anonymous methods also permit you to capture variables in the same scope.

Tip

Anonymous methods and lambda expressions are both subsets of anonymous functions. For the majority of situations, lambda expression syntax is preferable, and you should avoid using anonymous method syntax in C# 3.0. Almost anything that could be done using anonymous methods in C# 2.0 can now be done better with lambda expressions in C# 3.0.

For an example of an anonymous method, see the ExecuteCSharp2_0 method in the lambda expression section.

Lambda expressions are functions with a different syntax that enables them to be used in an expression context instead of the usual object-oriented method of being a member of a class. This means that with a single syntax, we can express a method definition, declaration, and the invocation of delegate to execute it, just as anonymous methods can, but with a more terse syntax.

A projection is a lambda expression that translates one type into another.

A lambda expression looks like this:

  j => j * 42

This means "using j as the parameter to the function, j goes to the result of j*42." The => can be thought of as "goes to" for both this and for a projection that was declared like this:

  j => new { Number = j*42 };

If you think about it, you can see that in C# 1.0 you could do the same thing:

 public delegate int IncreaseByANumber(int j);
    public delegate int MultipleIncreaseByANumber(int j, int k, int l);

    static public int MultiplyByANumber(int j) {
        return j * 42;
    }

    public static void ExecuteCSharp1_0()
    {
        IncreaseByANumber increase =
           new IncreaseByANumber(
               DelegatesEventsLambdaExpressions.MultiplyByANumber);
        Console.WriteLine(increase(10));
    }

In C# 2.0 with anonymous methods, the C# 1.0 syntax could be reduced to the following example, as it is no longer necessary to provide the name for the delegate since all we want is the result of the operation:

  public delegate int IncreaseByANumber(int j);

    public static void ExecuteCSharp2_0()
    {
        IncreaseByANumber increase = 
           new IncreaseByANumber(
            delegate(int j)
            {
                return j * 42;
            });
        Console.WriteLine(increase(10));
    }

This brings us back to C# 3.0 and lambda expressions, where we can now just write:

  public static void ExecuteCSharp3_0()
    {
        // declare the lambda expression
        IncreaseByANumber increase = j => j * 42;
        // invoke the method and print 420 to the console
        Console.WriteLine(increase(10));

        MultipleIncreaseByANumber multiple = (j, k, l) => ((j * 42) / k) % l;
        Console.WriteLine(multiple(10, 11, 12));
    }

Type inference helps the compiler to infer the type of j from the declaration of the IncreaseByANumber delegate type. If there were multiple arguments, then the lambda expression could look like this:

    MultipleIncreaseByANumber multiple = (j, k, l) => ((j * 42) / k) % l;
    Console.WriteLine(multiple(10, 11, 12));

This chapter's recipes make use of delegates, events, and lambda expressions. Among other topics, these recipes cover:

  • Handling each method invoked in a multicast delegate separately.

  • Synchronous delegate invocation versus asynchronous delegate invocation.

  • Enhancing an existing class with events.

  • Various uses of lambda expressions, closures, and functors.

If you are not familiar with delegates, events, or lambda expressions, you should read the MSDN documentation on these topics. There are also good tutorials and example code showing you how to set them up and use them in a basic fashion.

Controlling When and If a Delegate Fires Within a Multicast Delegate

Problem

You have combined multiple delegates to create a multicast delegate. When this multicast delegate is invoked, each delegate within it is invoked in turn. You need to exert more control over such things as the order in which each delegate is invoked, firing only a subset of delegates, or firing each delegate based on the success or failure of previous delegates.

Solution

Use the GetInvocationList method to obtain an array of Delegate objects. Next, iterate over this array using a for (if enumerating in a nonstandard order) or foreach (for enumerating in a standard order) loop. You can then invoke each Delegate object in the array individually and, optionally, retrieve its return value.

In C#, all delegate types support multicast-that is, any delegate instance can invoke multiple methods each time the instance is invoked if it has been set up to do so. In this recipe, we use the term multicast to describe a delegate that has been set up to invoke multiple methods.

The following method creates a multicast delegate called allInstances and then uses GetInvocationList to allow each delegate to be invoked individually, in reverse order. The Func<int> generic delegate is used to create delegate instances that return an int:

  public static void InvokeInReverse()
    {
        Func<int> myDelegateInstance1 = TestInvokeIntReturn.Method1;
        Func<int> myDelegateInstance2 = TestInvokeIntReturn.Method2;
        Func<int> myDelegateInstance3 = TestInvokeIntReturn.Method3;

        Func<int> allInstances =
                myDelegateInstance1 +
                myDelegateInstance2 +
                myDelegateInstance3;

        Console.WriteLine("Fire delegates in reverse");
        Delegate[] delegateList = allInstances.GetInvocationList();
        foreach (Func<int> instance in delegateList.Reverse())
        {
            instance();
        }
    }

Note that to roll over the delegate list retrieved using GetInvocationList, we use the IEnumerable<T> extension method Reverse so that we get the items in the opposite order the enumeration would normally produce them in.

As the following methods demonstrate by firing every other delegate, you don't have to invoke all of the delegates in the list. InvokeEveryOtherOperation uses an extension method created here for IEnumerable<T> called EveryOther that will only return every other item from the enumeration.

Tip

If a unicast delegate was used and you called GetInvocationList on it, you will receive a list of one delegate instance.

    public static void InvokeEveryOtherOperation()
    {
        Func<int> myDelegateInstance1 = TestInvokeIntReturn.Method1;
        Func<int> myDelegateInstance2 = TestInvokeIntReturn.Method2;
        Func<int> myDelegateInstance3 = TestInvokeIntReturn.Method3;

        Func<int> allInstances = //myDelegateInstance1;
                myDelegateInstance1 +
                myDelegateInstance2 +
                myDelegateInstance3;

        Delegate[] delegateList = allInstances.GetInvocationList();
        Console.WriteLine("Invoke every other delegate");
        foreach (Func<int> instance in delegateList.EveryOther())
        {
            // invoke the delegate
            int retVal = instance();
            Console.WriteLine("Delegate returned " + retVal);
        }
    }

    static IEnumerable<T> EveryOther<T>(this IEnumerable<T> enumerable)
    {
        bool retNext = true;
        foreach (T t in enumerable)
        {
            if (retNext) yield return t;
            retNext = !retNext;
        }
    }

The following class contains each of the methods that will be called by the multicast delegate allInstances:

    public class TestInvokeIntReturn
    {
        public static int Method1()
        {
            Console.WriteLine("Invoked Method1");
            return 1;
        }

        public static int Method2()
        {
            Console.WriteLine("Invoked Method2");
            return 2;
        }

        public static int Method3()
        {
            //throw (new Exception("Method1"));
            //throw (new SecurityException("Method3"));
            Console.WriteLine("Invoked Method3");
            return 3;
        }
    }

It is also possible to decide whether to continue firing delegates in the list based on the return value of the currently firing delegate. The following method fires each delegate, stopping only when a delegate returns a false value:

   public static void InvokeWithTest()
    {
        Func<bool> myDelegateInstanceBool1 = TestInvokeBoolReturn.Method1;
        Func<bool> myDelegateInstanceBool2 = TestInvokeBoolReturn.Method2;
        Func<bool> myDelegateInstanceBool3 = TestInvokeBoolReturn.Method3;

        Func<bool> allInstancesBool =
                myDelegateInstanceBool1 +
                myDelegateInstanceBool2 +
                myDelegateInstanceBool3;

        Console.WriteLine(
            "Invoke individually (Call based on previous return value):");
        foreach (Func<bool> instance in allInstancesBool.GetInvocationList())
        {
            if (!instance())
                break;
        }
    }

The following class contains each of the methods that will be called by the multicast delegate allInstancesBool:

    public class TestInvokeBoolReturn
    {
        public static bool Method1()
        {
            Console.WriteLine("Invoked Method1");
            return true;
        }

        public static bool Method2()
        {
            Console.WriteLine("Invoked Method2");
            return false;
        }

        public static bool Method3()
        {
            Console.WriteLine("Invoked Method3");
            return true;
        }
    }

Discussion

A delegate, when called, will invoke all delegates stored within its invocation list. These delegates are usually invoked sequentially from the first to the last one added. With the use of the GetInvocationList method of the MulticastDelegate class, you can obtain each delegate in the invocation list of a multicast delegate. This method accepts no parameters and returns an array of Delegate objects that corresponds to the invocation list of the delegate on which this method was called. The returned Delegate array contains the delegates of the invocation list in the order in which they would normally be called; that is, the first element in the Delegate array contains the Delegate object that is normally called first.

This application of the GetInvocationList method gives you the ability to control exactly when and how the delegates in a multicast delegate are invoked and allows you to prevent the continued invocation of delegates when one delegate fails. This ability is important if each delegate is manipulating data, and one of the delegates fails in its duties but does not throw an exception. If one delegate fails in its duties and the remaining delegates rely on all previous delegates to succeed, you must quit invoking delegates at the point of failure. Note that an exception will force the invocation of delegates to cease. Exceptions should only be used for exceptional circumstances, not for control flow. This recipe handles a delegate failure more efficiently and also provides more flexibility in dealing with these errors. For example, you can write logic to specify which delegates are to be invoked, based on the returned values of previously invoked delegates.

See Also

Recipes 9.2 and 9.3; see the "Delegate Class" and "Delegate.GetInvocationList Method" topics in the MSDN documentation.

Obtaining Return Values from Each Delegate in a Multicast Delegate

Problem

You have added multiple delegates to a single multicast delegate. Each of these individual delegates returns a value that is required by your application. Ordinarily, the values returned by individual delegates in a multicast delegate are lost-all except the value from the last delegate to fire, the return value of which is returned to the calling application. You need to be able to access the return value of each delegate that is invoked in the multicast delegate.

Solution

Use the GetInvocationList method as in the section called "Controlling When and If a Delegate Fires Within a Multicast Delegate". This method returns each individual delegate from a multicast delegate. In doing so, you can invoke each delegate individually and get its return value. The following method creates a multicast delegate called All and then uses GetInvocationList to fire each delegate individually. After firing each delegate, the return value is captured:

  public static void TestIndividualInvokesReturnValue()
    {
        Func<int> myDelegateInstance1 = TestInvokeIntReturn.Method1;
        Func<int> myDelegateInstance2 = TestInvokeIntReturn.Method2;
        Func<int> myDelegateInstance3 = TestInvokeIntReturn.Method3;

        Func<int> allInstances =
                myDelegateInstance1 +
                myDelegateInstance2 +
                myDelegateInstance3;

        Console.WriteLine("Invoke individually (Obtain each return value):");
        foreach (Func<int> instance in allInstances.GetInvocationList())
        {
            int retVal = instance();
            Console.WriteLine("\tOutput: " + retVal);
        }
    }

This sample uses the TestInvokeIntReturn class defined in the section called "Controlling When and If a Delegate Fires Within a Multicast Delegate".

Discussion

One quirk with multicast delegates is that if any or all delegates within its invocation list return a value, only the value of the last invoked delegate is returned; all others are lost. This loss can become annoying, or worse, if your code requires these return values. Consider a case in which the allInstances delegate was invoked normally, as in the following code:

    retVal = allInstances();
    Console.WriteLine(retVal);

The value 3 would be displayed because Method3 was the last method invoked by the allInstances delegate. None of the other return values would be captured.

By using the GetInvocationList method of the MulticastDelegate class, you can get around this limitation. This method returns an array of Delegate objects that can each be invoked separately. Note that this method does not invoke each delegate; it simply returns an array of them to the caller. By invoking each delegate separately, you can retrieve each return value from each invoked delegate. (More information on the GetInvocationList method is presented in the section called "Controlling When and If a Delegate Fires Within a Multicast Delegate".)

Note that any out or ref parameters will also be lost when a multicast delegate is invoked. This recipe allows you to obtain the out and/or ref parameters of each invoked delegate within the multicast delegate.

However, you still need to be aware that any unhandled exceptions emanating from one of these invoked delegates will be bubbled up to the method TestIndividualInvokesReturnValue presented in this recipe. To better handle this situation, see the section called "Handling Exceptions Individually for Each Delegate in a Multicast Delegate".

See Also

Recipes 9.1 and 9.3; see the "Delegate Class" and "Delegate.GetInvocationList Method" topics in the MSDN documentation.

Handling Exceptions Individually for Each Delegate in a Multicast Delegate

Problem

You have added multiple delegates to a single multicast delegate. Each of these individual delegates must be invoked, regardless of whether an unhandled exception is thrown within one of the delegates. But once a delegate in a multicast delegate throws an unhandled exception, no more delegates are invoked. You need a way to trap unhandled exceptions within each individual delegate while still allowing the rest of the delegates to fire.

Solution

Use the GetInvocationList method as shown in the section called "Controlling When and If a Delegate Fires Within a Multicast Delegate". This method returns each individual delegate from a multicast delegate and, by doing so, allows you to invoke each delegate within the try block of an exception handler.

The following delegate defines the MyDelegateOperation delegate type:

   public delegate int MyDelegateOperation();

The method shown in Example 9-1, "Handling exceptions individually for each delegate in a multicast delegate" creates a multicast delegate called allInstances and then uses GetInvocationList to retrieve each delegate individually. Each delegate is then invoked within the try block of an exception handler.

Example 9-1. Handling exceptions individually for each delegate in a multicast delegate

public static void TestIndividualInvokesExceptions()
{

    Func<int> myDelegateInstance1 = TestInvokeIntReturn.Method1;
    Func<int> myDelegateInstance2 = TestInvokeIntReturn.Method2;
    Func<int> myDelegateInstance3 = TestInvokeIntReturn.Method3;

    Func<int> allInstances =
            myDelegateInstance1 +
            myDelegateInstance2 +
            myDelegateInstance3;

    Console.WriteLine("Invoke individually (handle exceptions):");

    // Create an instance of a wrapper exception to hold any exceptions
    // encountered during the invocations of the delegate instances
    List<Exception> invocationExceptions = new List<Exception>();

    foreach (Func<int> instance in allInstances.GetInvocationList())
    {
        try
        {
            int retVal = instance();
            Console.WriteLine("\tOutput: " + retVal);
        }
        catch (Exception ex)
        {
            // Display and log the exception and continue
            Console.WriteLine(ex.ToString());
            EventLog myLog = new EventLog();
            myLog.Source = "MyApplicationSource";
            myLog.WriteEntry("Failure invoking " +
                instance.Method.Name + " with error " +
                ex.ToString(),
                EventLogEntryType.Error);
            // add this exception to the list
            invocationExceptions.Add(ex);
        }
    }
    // if we caught any exceptions along the way, throw our
    // wrapper exception with all of them in it.
    if (invocationExceptions.Count > 0)
    {
        throw new MulticastInvocationException(invocationExceptions);
    }
}

The MulticastInvocationException class is able to have multiple exceptions added to it. It exposes an ReadOnlyCollection<Exception> through the InvocationExceptions property, as shown in Example 9-2, "MulticastInvocationException class".

Example 9-2. MulticastInvocationException class

[Serializable]
public class MulticastInvocationException : Exception
{
    private List<Exception> _invocationExceptions;

    public MulticastInvocationException()

        : base()
    {
    }

    public MulticastInvocationException(IEnumerable<Exception> invocationExceptions)
    {
        _invocationExceptions = new List<Exception>(invocationExceptions);
    }

    public MulticastInvocationException(string message)
        : base(message)
    {
    }

    public MulticastInvocationException(string message, Exception innerException) 
        :base(message,innerException)
    {
    }

    protected MulticastInvocationException(SerializationInfo info, StreamingContext
context) :
        base(info, context)
    {
        _invocationExceptions =
            (List<Exception>)info.GetValue("InvocationExceptions",
                typeof(List<Exception>));
    }

    [SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter = true)]
    public override void GetObjectData(
       SerializationInfo info, StreamingContext context)
    {
        info.AddValue("InvocationExceptions", this.InvocationExceptions);
        base.GetObjectData(info, context);
    }

    public ReadOnlyCollection<Exception> InvocationExceptions
    {
        get { return new ReadOnlyCollection<Exception>(_invocationExceptions); }
    }
}

This sample uses the TestInvokeIntReturn class defined in the section called "Controlling When and If a Delegate Fires Within a Multicast Delegate".

Discussion

If an exception occurs in a delegate that is invoked from within a multicast delegate and that exception is unhandled, any remaining delegates are not invoked. This is the expected behavior of a multicast delegate. However, in some circumstances, you'd like to be able to handle exceptions thrown from individual delegates and then determine at that point whether to continue invoking the remaining delegates.

In the TestIndividualInvokesExceptions method of this recipe, if an exception is caught, it is logged to the event log and displayed, then the code continues to invoke delegates. This strategy allows for as fine-grained handling of exceptions as you need. One way to deal with this is to store all of the exceptions that occur during delegate processing, and then wrap all of the exceptions encountered during processing in a custom exception. After processing completes, throw the custom exception. See the MulticastInvocationException class in the Solution.

By adding a finally block to this try-catch block, you could be assured that code within this finally block is executed after every delegate returns. This technique is useful if you want to interleave code between calls to delegates, such as code to clean up objects that are not needed or code to verify that each delegate left the data it touched in a stable state.

See Also

Recipes 9.1 and 9.2; see the "Delegate Class" and "Delegate.GetInvocationList Method" topics in the MSDN documentation.

Converting Delegate Invocation from Synchronous to Asynchronous

Problem

You have determined that one or more delegates invoked synchronously within your application are taking a long time to execute. This delay is making the user interface less responsive to the user. The invocation of these delegates should be converted from synchronous to asynchronous mode.

Solution

A typical synchronous delegate type and supporting code that invokes the delegate are shown here:

  public delegate void SyncDelegateTypeSimple();

    public class TestSyncDelegateTypeSimple
    {
        public static void Method1()
        {
            Console.WriteLine("Invoked Method1");
        }
    }

The code to use this delegate is:

   public static void TestSimpleSyncDelegate()
    {
        SyncDelegateTypeSimple sdtsInstance = TestSyncDelegateTypeSimple.Method1;
        sdtsInstance();
    }

This delegate can be called asynchronously on a thread obtained from the thread pool by modifying the code as follows:

  public static void TestSimpleAsyncDelegate()
    {
        AsyncCallback callBack = new AsyncCallback(DelegateSimpleCallback);

        SyncDelegateTypeSimple sdtsInstance = TestSyncDelegateTypeSimple.Method1;

        IAsyncResult asyncResult =
            sdtsInstance.BeginInvoke(callBack, null);

        Console.WriteLine("WORKING...");
    }

    // The callback that gets called when TestSyncDelegateTypeSimple.Method1
    // is finished processing
    private static void DelegateSimpleCallback(IAsyncResult iResult)
    {
        AsyncResult result = (AsyncResult)iResult;
        SyncDelegateTypeSimple sdtsInstance =
            (SyncDelegateTypeSimple)result.AsyncDelegate;

        sdtsInstance.EndInvoke(result);
        Console.WriteLine("Simple callback run");
    }

Tip

AsyncResult can be found in the System.Runtime.Remoting.Messaging namespace in mscorlib.

Of course, you might also want to change the TestSyncDelegateTypeSimple class name to TestAsyncDelegateTypeSimple and the SyncDelegateTypeSimple delegate name to AsyncDelegateTypeSimple just to be consistent with your naming.

The previous example shows how to call a delegate that accepts no parameters and returns void. The next example shows a synchronous delegate that accepts parameters and returns an integer:

    public delegate int SyncDelegateType(string message);
    public class TestSyncDelegateType
    {
        public static int Method1(string message)
        {
            Console.WriteLine("Invoked Method1 with message: " + message);
            return 1;
        }
    }

The code to use this delegate is:

   public static void TestComplexSyncDelegate()
    {
        SyncDelegateType sdtInstance = TestSyncDelegateType.Method1;

        int retVal = sdtInstance("Synchronous call");

        Console.WriteLine("Sync: " + retVal);
    }

The synchronous invocation of the delegate can be converted to asynchronous invocation in the following manner:

 public static void TestCallbackAsyncDelegate()
    {
        AsyncCallback callBack =
            new AsyncCallback(DelegateCallback);

        SyncDelegateType sdtInstance = TestSyncDelegateType.Method1;

        IAsyncResult asyncResult =
            sdtInstance.BeginInvoke("Asynchronous call", callBack, null);

        Console.WriteLine("WORKING...");
    }

    // The callback that gets called when TestSyncDelegateType.Method1
    // is finished processing
    private static void DelegateCallback(IAsyncResult iResult)
    {

        AsyncResult result = (AsyncResult)iResult;
        SyncDelegateType sdtInstance =
            (SyncDelegateType)result.AsyncDelegate;

        int retVal = sdtInstance.EndInvoke(result);
        Console.WriteLine("retVal (Callback): " + retVal);
    }

Discussion

Converting the invocation of a delegate from being synchronous to asynchronous is not an overly complicated procedure. You need to add calls to both BeginInvoke and EndInvoke on the delegate that is being called synchronously. A callback method, DelegateCallback, is added, which gets called when the delegate is finished. This callback method then calls the EndInvoke method on the delegate invoked using BeginInvoke.

Tip

You must always call EndInvoke when invoking delegates asynchronously, even when the delegate returns void, to ensure proper cleanup of resources in the CLR.

The notification callback method specified in the callback parameter accepts a single parameter of type IAsyncResult. This parameter can be cast to an AsyncResult type and used to set up the call to the EndInvoke method. If you want to handle any exceptions thrown by the asynchronous delegate in the notification callback, wrap the EndInvoke method in a try/catch exception handler.

See Also

The "Delegate Class" and "Asynchronous Delegates" topics in the MSDN documentation.

An Advanced Interface Search Mechanism

Problem

You are searching for an interface using the Type class. However, complex interface searches are not available through the GetInterface and GetInterfaces methods of a Type object. The GetInterface method searches for an interface only by name (using a case-sensitive or case-insensitive search), and the GetInterfaces method returns an array of all the interfaces implemented on a particular type. You want a more focused searching mechanism that might involve searching for interfaces that define a method with a specific signature or implemented interfaces that are loaded from the GAC. Youneed more flexible and more advanced searching for interfaces that does not involve creating your own interface search engine. This capability might be used for applications like a code generator or reverse engineering tool.

Solution

Use LINQ to query the type interface information and perform rich searches. The method shown in Example 9-3, "Performing complex searches of interfaces on a type" will demonstrate one complex search that can be performed with LINQ.

Example 9-3. Performing complex searches of interfaces on a type

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;


public class SearchType
{
    public static void FindSpecificInterfaces()
    {
        // set up the interfaces to search for
        Type[] interfaces = {
            typeof(System.ICloneable),
            typeof(System.Collections.ICollection),
            typeof(System.IAppDomainSetup) };

       // set up the type to examine
       Type searchType = typeof(System.Collections.ArrayList);

       var matches = from t in searchType.GetInterfaces()
                     join s in interfaces on t equals s
                     select s;

       Console.WriteLine("Matches found:");
       foreach (Type match in matches)
       {
           Console.WriteLine(match.ToString());
       }
       }
}

The FindSpecificInterfaces method searches for any of the three interface types contained in the Names array that are implemented by the System.Collections. ArrayList type. It does this by using LINQ to query if the type is an instance of any of the set of interfaces.

Discussion

There are many ways to use LINQ to search for interfaces implemented on a type- here are just a few other searches that can be performed:

  • A search for all implemented interfaces that are defined within a particular namespace (in this case, the System.Collections namespace):

        var collectionsInterfaces = from type in searchType.GetInterfaces()
                                    where type.Namespace == "System.Collections"
                                    select type;
    
  • A search for all implemented interfaces that contain a method called Add, which returns an Int32 value:

     var addInterfaces = from type in searchType.GetInterfaces()
                                   from method in type.GetMethods()
                                   where (method.Name == "Add") &&
                                         (method.ReturnType == typeof(int))
                                   select type;
    
  • A search for all implemented interfaces that are loaded from the GAC:

        var gacInterfaces = from type in searchType.GetInterfaces()
                            where type.Assembly.GlobalAssemblyCache
                            select type;
    
  • A search for all implemented interfaces that are defined within an assembly with the version number 2.0.0.0:

        var versionInterfaces = from type in searchType.GetInterfaces()
                                where type.Assembly.GlobalAssemblyCache
                                select type;
    

See Also

The "Lambda Expressions (C# Programming Guide)" and "where keyword [LINQ] (C#)" topics in the MSDN documentation.

Observing Additions and Modifications to Dictionaries

Problem

You have multiple objects that need to observe modifications to objects that implement IDictionary<K,V>. When an item is added or modified in the dictionary-based collection, each of these observer objects should be able to vote to allow or disallow the action. In order for an action to be allowed to complete, all observer objects must state if they are vetoing the action. If even one observer object votes to disallow the action, the action is prevented.

Solution

Use the ObservableDictionaryObserver class implemented in Example 9-5, "ObservableDictionaryObserver class" to observe additions and modifications to the ObservableDictionary class (shown in Example 9-4, "ObservableDictionary and ObservableDictionaryEventArgs classes and the MakeObservableDictionary extension method") object that is registered with this object. The ObservableDictionary class is a generic wrapper for collections that implement IDictionary<K,V> and allows itself to be observed by the ObservableDictionaryObserver class.

The ObservableDictionaryEventArgs class is a specialization of the EventArgs class, which provides the IDictionary<K,V> key and value being added or modified to the ObservableDictionaryObserver object, as well as a Boolean property, KeepChanges. This flag indicates whether the addition or modification in the ObservableDictionary object will succeed or be rolled back. The MakeObservableDictionary extension method for IDictionary<K,V> wraps up the code for creating an ObservableDictionary from an IDictionary instance. Example 9-4, "ObservableDictionary and ObservableDictionaryEventArgs classes and the MakeObservableDictionary extension method" illustrates the two classes and the extension method.

Example 9-4. ObservableDictionary and ObservableDictionaryEventArgs classes and the MakeObservableDictionary extension method

public class ObservableDictionary<TKey,TValue> : IDictionary<TKey,TValue>
{
    IDictionary<TKey, TValue> _internalDictionary;
    public ObservableDictionary(IDictionary<TKey,TValue> dictionary)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");
        _internalDictionary = dictionary;
    }

    #region Events and Event Initiation

    public event EventHandler<ObservableDictionaryEventArgs<TKey,TValue>> AddingEntry;
    public event EventHandler<ObservableDictionaryEventArgs<TKey, TValue>> AddedEntry;
    public event EventHandler<ObservableDictionaryEventArgs<TKey, TValue>> ChangingEntry;
    public event EventHandler<ObservableDictionaryEventArgs<TKey, TValue>> ChangedEntry;

    protected virtual bool OnAdding(ObservableDictionaryEventArgs<TKey,TValue> e)
    {
        if (AddingEntry != null)
        {
            AddingEntry(this, e);
            return (e.KeepChanges);
        }

        return (true);
    }

    protected virtual void OnAdded(ObservableDictionaryEventArgs<TKey, TValue> e)
    {
        if (AddedEntry != null)
        {
            AddedEntry(this, e);
        }
    }

    protected virtual bool OnChanging(ObservableDictionaryEventArgs<TKey, TValue> e)
    {
        if (ChangingEntry != null)
        {
            ChangingEntry(this, e);
            return (e.KeepChanges);
        }

        return (true);
    }

    protected virtual void OnChanged(ObservableDictionaryEventArgs<TKey, TValue> e)
    {
        if (ChangedEntry != null)
        {
            ChangedEntry(this, e);
        }
    }
    #endregion // Events and Event Initiation

    #region Interface implementations
    #region IDictionary<TKey,TValue> Members

    public ICollection<TValue> Values
    {

        get { return _internalDictionary.Values; }
    }

    public ICollection<TKey> Keys
    {
        get { return _internalDictionary.Keys; }
    }

    public TValue this[TKey key]
    {
        get
        {
            TValue value;
            if (_internalDictionary.TryGetValue(key, out value))
                return value;
            else
            {
                return default(TValue);
            }
        }
        set
        {
            // see if this key is there to be changed, if not add it
            if (_internalDictionary.ContainsKey(key))
            {
                ObservableDictionaryEventArgs<TKey, TValue> args =
                    new ObservableDictionaryEventArgs<TKey, TValue>(key, value);

                if (OnChanging(args))
                {
                    _internalDictionary[key] = value;
                }
                else
                {
                    Debug.WriteLine("Change of value cannot be performed");
                }

                OnChanged(args);
            }
            else
            {
                Debug.WriteLine("Item did not exist, adding");
                _internalDictionary.Add(key, value);
            }
        }
    }

    public void Add(TKey key, TValue value)
    {
        ObservableDictionaryEventArgs<TKey, TValue> args =
            new ObservableDictionaryEventArgs<TKey, TValue>(key, value);

        if (OnAdding(args))
        {
            this._internalDictionary.Add(key, value);
        }
        else
        {
            Debug.WriteLine("Addition of key/value cannot be performed");
        }

        OnAdded(args);
    }

    public bool ContainsKey(TKey key)
    {
        return _internalDictionary.ContainsKey(key);
    }

    public bool Remove(TKey key)
    {
        return _internalDictionary.Remove(key);
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        return _internalDictionary.TryGetValue(key, out value);
    }

    #endregion

    #region ICollection<KeyValuePair<TKey,TValue>> Members

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        _internalDictionary.Add(item.Key, item.Value);
    }

    public void Clear()
    {
        _internalDictionary.Clear();
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
         return _internalDictionary.Contains(item);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        _internalDictionary.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return _internalDictionary.Count; }
    }

    public bool IsReadOnly
     {
        get { return _internalDictionary.IsReadOnly; }
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        return _internalDictionary.Remove(item);
    }

    #endregion

    #region IEnumerable<KeyValuePair<TKey,TValue>> Members

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return _internalDictionary.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _internalDictionary.GetEnumerator();
    }

    #endregion
    #endregion // Interface implementations
}

public static ObservableDictionary<TKey, TValue> MakeObservableDictionary<TKey, TValue>(
    this IDictionary<TKey, TValue> dictionary)
{
    return new ObservableDictionary<TKey, TValue>(dictionary);
}

public class ObservableDictionaryEventArgs<TKey, TValue> : EventArgs
{
    TKey _key;
    TValue _value;

    public ObservableDictionaryEventArgs(TKey key, TValue value)
    {
        _key = key;
        _value = value;
        this.KeepChanges = true;
    }

    public bool KeepChanges { get; set; }
    public TKey Key { get { return _key; }}
    public TValue Value { get { return _value; } }
}

Example 9-5, "ObservableDictionaryObserver class" shows the code for the ObservableDictionaryObserver class.

Example 9-5. ObservableDictionaryObserver class

// The observer object that will observe a registered ObservableDictionary object
public class ObservableDictionaryObserver<TKey,TValue>
{
    public ObservableDictionaryObserver() { }

    // set up delegate/events for approving an addition or change
    public delegate bool Approval(object sender,
            ObservableDictionaryEventArgs<TKey,TValue> e);

    public Approval ApproveAdd { get; set; }
    public Approval ApproveChange { get; set; }

    public void Register(ObservableDictionary<TKey, TValue> dictionary)
    {
        // hook up to the ObservableDictionary instance events
        dictionary.AddingEntry +=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnAddingListener);
        dictionary.AddedEntry +=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnAddedListener);
        dictionary.ChangingEntry +=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnChangingListener);
        dictionary.ChangedEntry +=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnChangedListener);
    }

    public void Unregister(ObservableDictionary<TKey,TValue> dictionary)
    {
        // Unhook from the ObservableDictionary instance events
        dictionary.AddingEntry -=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnAddingListener);
        dictionary.AddedEntry -=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnAddedListener);

        dictionary.ChangingEntry -=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnChangingListener);
        dictionary.ChangedEntry -=
            new EventHandler<ObservableDictionaryEventArgs<TKey, TValue>>(
                                                   OnChangedListener);
    }

    private void CheckApproval(Approval approval,
            ObservableDictionaryEventArgs<TKey,TValue> args)
    {
        // check everyone who wants to approve
        foreach (Approval approvalInstance in
                        approval.GetInvocationList())
        {
            if (!approvalInstance(this,args))
            {
                // if any of the concerned parties
                // refuse, then no add. Adds by default
                args.KeepChanges = false;
                break;
            }
       }
    }

    private void OnAddingListener(object sender,
                ObservableDictionaryEventArgs<TKey,TValue> args)
    {
        // see if anyone hooked up for approval
        if (ApproveAdd != null)
        {
            CheckApproval(ApproveAdd, args);
        }

        Debug.WriteLine("[NOTIFY] Before Add...: Add Approval = " +
                            args.KeepChanges.ToString());
    }

    private void OnAddedListener(object sender,
            ObservableDictionaryEventArgs<TKey, TValue> args)
    {
        Debug.WriteLine("[NOTIFY] ...After Add:   Item approved for adding: " +
                            args.KeepChanges.ToString());
    }

    private void OnChangingListener(object sender,
            ObservableDictionaryEventArgs<TKey, TValue> args)
    {
        // see if anyone hooked up for approval
        if (ApproveChange != null)
        {
            CheckApproval(ApproveChange, args);
        }

        Debug.WriteLine("[NOTIFY] Before Change...: Change Approval = " +
                            args.KeepChanges.ToString());
    }

    private void OnChangedListener(object sender,
            ObservableDictionaryEventArgs<TKey, TValue> args)
    {

    Debug.WriteLine("[NOTIFY] ...After Change: Item approved for change: " +
                        args.KeepChanges.ToString());
    }
}

Discussion

The observer design pattern allows one or more observer objects to act as spectators over one or more subjects. Not only do the observer objects act as spectators, but they can also induce change in the subjects. According to this pattern, any subject is allowed to register itself with one or more observer objects. Once this is done, the subject can operate as it normally does. The key feature is that the subject doesn't have to know what it is being observed by; this allows the coupling between subjects and observers to be minimized. The observer object(s) will then be notified of any changes in state to the subjects. When the subject's state changes, the observer object(s) can change the state of other objects in the system to bring them into line with changes that were made to the subject(s). In addition, the observer could even make changes or refuse changes to the subject(s) themselves.

The observer pattern is best implemented with events in C#. The event object provides a built-in way of implementing the observer design pattern. This recipe implements this pattern on all collections supporting IDictionary<K,V>. The object being observed must raise events for any listening observer objects to handle, but the IDictionary<K,V> interface found in the FCL does not indicate any events. In order to make the IDictionary<K,V> raise events at specific times, you must implement a wrapper class, ObservableDictionary, that implements the IDictionary<K,V> interface. This ObservableDictionary class overrides the Add and indexer members of the base interface. In addition, four events (AddingEntry, AddedEntry, ChangingEntry, and ChangedEntry) are created; they will be raised before and after items are added or modified in the ObservableDictionary. To raise these events, the following four methods are created, one to raise each event:

  • The OnAdding method raises the AddingEntry event.

  • The OnAdded method raises the AddedEntry event.

  • The OnChanging method raises the ChangingEntry event.

  • The OnChanged method raises the ChangedEntry event.

The Add method calls the OnAdding method, which then raises the event to any listening observer objects. The OnAdding method is called before the Add method on the internal dictionary is called. After the key/value pair has been added, the OnAdded method is called. This operation is similar to the indexer set method.

Tip

The Onxxx methods that raise the events in the ObservableDictionary class are marked as protected virtual to allow classes to subclass this class and implement their own method of dealing with the events. Note that this statement is not applicable to sealed classes. In those cases, you can simply make the methods public.

The ObservableDictionaryEventArgs class contains three private fields, defined as follows:

  • key
    The key that is to be added to the dictionary.

  • value
    The value that is to be added to the dictionary.

  • keepChanges
    A flag indicating whether the key/value pair should be added to the dictionary. true indicates that this pair should be added to the dictionary.

The keepChanges field is used by the observer to determine whether an add or change operation should proceed. This flag is discussed further when you look at the ObservableDictionaryObserver observer object.

The ObservableDictionaryObserver is the observer object that watches any ObservableDictionary objects it is told about. Any ObservableDictionary object can be passed to the ObservableDictionaryObserver.Register method in order to be observed. This method accepts an ObservableDictionary object (dictionary) as its only parameter. This method then hooks up the event handlers in the ObservableDictionaryObserver object to the events that can be raised by the ObservableDictionary object passed in through the dictionary parameter. Therefore, the following events and event handlers are bound together:

  • The ObservableDictionary.AddingEntry event is bound to the ObservableDictionaryObserver.OnAddingListener event handler.

  • The ObservableDictionary.AddedEntry event is bound to the ObservableDictionaryObserver.OnAddedListener event handler.

  • The ObservableDictionary.ChangingEntry event is bound to the ObservableDictionaryObserver.OnChangingListener event handler.

  • The ObservableDictionary.ChangedEntry event is bound to the ObservableDictionaryObserver.OnChangedListener event handler.

The OnAddingListener and OnChangingListener methods watch for additions and changes to the key/value pairs of the watched ObservableDictionary object(s). Since you have an event firing before and after an addition or modification occurs, you can determine whether the addition or change should occur.

Two events are published by the ObservableDictionaryObserver to allow for an external entity to approve or deny the addition or changing of an entry. These events are named ApproveAdd and ApproveChange, respectively, and are of delegate type Approval as shown below:

 public delegate bool Approval(object sender,
            ObservableDictionaryEventArgs<TKey,TValue> e);

This is where the keepChanges field of the ObservableDictionaryEventArgs object comes into play. If an external source wants to block the addition or change, it can simply return false from its event handler implementation of the appropriate Approve* event.

The ObservableDictionaryObserver object will set this flag according to whether it determines that the action should proceed or be prematurely terminated. The ObservableDictionaryEventArgs object is passed back to the OnAdding and OnChanging methods. These methods then return the value of the KeepChanges property to either the calling Add method or indexer. The Add method or indexer then uses this flag to determine whether the internal dictionary object should be updated.

The code in Example 9-6, "Using the ObservableDictionary and ObservableDictionaryObserver classes" shows how to instantiate ObservableDictionaries and ObservableDictionaryObservers and how to register, set up approval, use, and unregister them.

Example 9-6. Using the ObservableDictionary and ObservableDictionaryObserver classes

public static void TestObserverPattern( )
{
    Dictionary<int, string> dictionary1 = new Dictionary<int, string>( );
    Dictionary<int, string> dictionary2 = new Dictionary<int, string>( );
    Dictionary<int, string> dictionary3 = new Dictionary<int, string>( );

    // Create three observable dictionary instances
    var obsDict1 = dictionary1.MakeObservableDictionary( );
    var obsDict2 = dictionary2.MakeObservableDictionary( );
    var obsDict3 = dictionary3.MakeObservableDictionary( );

    // Create an observer for the three subject objects
    var observer = new ObservableDictionaryObserver<int, string>( );

    // Register the three subjects with the observer
    observer.Register(obsDict1);
    observer.Register(obsDict2);
    observer.Register(obsDict3);

    // hook up the approval events for adding or changing
    observer.ApproveAdd +=
        new ObservableDictionaryObserver<int, string>.
            Approval(SeekApproval);
    observer.ApproveChange +=
        new ObservableDictionaryObserver<int, string>.
            Approval(SeekApproval);

    // Use the observable instances
    obsDict1.Add(1, "one");
    obsDict2.Add(2, "two");
    obsDict3.Add(3, "three");

    // Insure the approval process worked
    Debug.Assert(obsDict1.Count == 1);
    Debug.Assert(obsDict2.Count == 1);
    // this should be empty as the value was more than three characters
    Debug.Assert(obsDict3.Count == 0);

    // Unregister the observable instances
    observer.Unregister(obsDict3);
    observer.Unregister(obsDict2);
    observer.Unregister(obsDict1);

    ///////////////////////////////////////////////////////////////
    // Now do it with a different type of dictionary
    ///////////////////////////////////////////////////////////////
    // Create two observable SortedList instances
    SortedList<string, bool> sortedList1 = new SortedList<string, bool>( );
    SortedList<string, bool> sortedList2 = new SortedList<string, bool>( );

    var obsSortedList1 = sortedList1.MakeObservableDictionary( );
    var obsSortedList2 = sortedList2.MakeObservableDictionary( );

    // Create an observer for the two subject objects
    ObservableDictionaryObserver<string, bool> listObserver =
        new ObservableDictionaryObserver<string, bool>( );

    // Register the three subjects with the observer
    listObserver.Register(obsSortedList1);
    listObserver.Register(obsSortedList2);

    // hook up the approval events for adding or changing
    listObserver.ApproveAdd +=
        new ObservableDictionaryObserver<string, bool>.
            Approval(ApprovePositive);
    listObserver.ApproveChange +=
        new ObservableDictionaryObserver<string, bool>.
            Approval(ApprovePositive);

    // Use the observable instances
    obsSortedList1.Add("Item 1",true);
    obsSortedList2.Add("Item 2", false);

    // Insure the approval process worked
    Debug.Assert(obsSortedList1.Count == 1);
    // this should be empty as only true values are taken
    Debug.Assert(obsSortedList2.Count == 0);

    // Unregister the observable instances
    listObserver.Unregister(obsSortedList2);
    listObserver.Unregister(obsSortedList1);
}

static bool SeekApproval(object sender,
        ObservableDictionaryEventArgs<int, string> args)
{
    // only allow strings of no more than 3 characters in
    // our dictionary
    string value = args.Value.ToString( );
    if (value.Length <= 3)
        return true;
    return false;
}

static bool ApprovePositive(object sender,
        ObservableDictionaryEventArgs<string, bool> args)
{
    // only allow positive values
    return args.Value;
}

Note that if the ObservableDictionaries are used without registering them, no events will be raised. Since no events are raised, the observer cannot do its job, and values may be added to the unregistered subjects that are out of bounds for the application.

When using the observer design pattern in this fashion, keep in mind that fine-grained events, such as the ones in this recipe, could possibly drag down performance, so set a goal and then profile your code. If you have many subjects raising many events, your application could fail to meet performance expectations.

Notice that in the second set of code exercising the ObservableDictionary,a SortedList<K,V> is used instead of a Dictionary<K,V> with no difference in the usage patterns or results:

    // Use Dictionary<int,string> as the base
    Dictionary<int, string> dictionary1 = new Dictionary<int, string>();
    var obsDict1 = dictionary1.MakeObservableDictionary();

    // Use SortedList<string,bool> as the base
    SortedList<string, bool> sortedList1 = new SortedList<string, bool>();
    var obsSortedList1 = sortedList1.MakeObservableDictionary();

See Also

The "Event Keyword," "EventHandler Delegate," "EventArgs Class," and "Handling and Raising Events" topics in the MSDN documentation.

Using Lambda Expressions

Problem

There is a feature in C# 3.0 called lambda expressions. While lambda expressions can be viewed as syntactic sugar for making anonymous method definition less difficult, you want to understand all of the different ways that they can be used to help you in your daily programming chores as well as understand the ramifications of those uses.

Solution

Lambda expressions can be implemented by the compiler from methods created by the developer. There are two orthogonal characteristics that lambda expressions may have:

  • Parameter lists may have explicit or implicit types.

  • Bodies may be expressions or statement blocks.

Let's start with the original way to use delegates. First, you would declare a delegate type, DoWork in this case, and then you would create an instance of it (as shown here in the WorkItOut method). Declaring the instance of the delegate requires that you specify a method to execute when the delegate is invoked, and here the DoWorkMethodImpl method has been connected. The delegate is invoked, and the text is written to the console via the DoWorkMethodImpl method:

 class OldWay
    {
                // declare delegate
                delegate int DoWork(string work);

                // have a method to create an instance of and call the delegate
                public void WorkItOut( )
                {
                            // declare instance
                            DoWork dw = new DoWork(DoWorkMethodImpl);
                            // invoke delegate
                            int i = dw("Do work the old way");
                }

                // Have a method that the delegate is tied to with a matching signature
                // so that it is invoked when the delegate is called
                public int DoWorkMethodImpl(string s)
                {
                            Console.WriteLine(s);
                            return s.GetHashCode( );
                }
    }

Lambda expressions allow you to set up code to run when a delegate is invoked, but there does not need to be a named formal method declaration that is given to the delegate. The method thus declared is nameless and closed over the scope of the outer method. For example, you could have written the preceding code using a lambda expression such as this:

    class LambdaWay
    {
                // declare delegate
                delegate int DoWork(string work);

                // have a method to create an instance of and call the delegate
                public void WorkItOut( )
                {
                            // declare instance
                            DoWork dw = s =>
                            {
                                        Console.WriteLine(s);
                                        return s.GetHashCode( );
                            };
                            // invoke delegate
                            int i = dw("Do some inline work");
                }
    }

Notice that instead of having a method called DoWorkMethodImpl, you use the => operator to directly assign the code from that method inline to the DoWork delegate. The assignment looks like this:

  DoWork dw = s =>
    {
                Console.WriteLine(s);
                return s.GetHashCode( );
    };

You also provide the parameter required by the DoWork delegate (string), and your code returns an int (s.GetHashCode()) as the delegate requires. When setting up a lambda expression, the code must "match" the delegate signature, or you will get a compiler error.

By match we mean:

If explicitly typed, the lambda parameters must exactly match the delegate parameters. If implicitly typed, the lambda parameters get the delegate parameter types.

The body of the lambda must be a legal expression or statement block given the parameter types.

The return type of the lambda must be implicitly convertible to the return type of the delegate. It need not match exactly.

There is yet another way you can set up the delegate, and that is through the magic of delegate inference. Delegate inference allows you to assign the method name directly to the delegate instance without having to write the code for creating a new delegate object. Under the covers, C# actually writes the IL for creating the delegate object, but you don't have to do it explicitly here. Using delegate inference instead of writing out new [Delegate Type]([Method Name]) everywhere helps to unclutter the code involved in the usage of delegates, as shown here:

   class DirectAssignmentWay
    {
                // declare delegate
                delegate int DoWork(string work);

                // have a method to create an instance of and call the delegate
                public void WorkItOut( )
                {
                            // declare instance and assign method
                            DoWork dw = DoWorkMethodImpl;
                            // invoke delegate
                            int i = dw("Do some direct assignment work");
                }
                // Have a method that the delegate is tied to with a matching signature
                // so that it is invoked when the delegate is called
                public int DoWorkMethodImpl(string s)
                {
                            Console.WriteLine(s);
                            return s.GetHashCode( );
                }
    }

Notice that all that is assigned to the DoWork delegate instance dw is the method name DoWorkMethodImpl. There is no "new DoWork(DoWorkMethodImpl)" call as there was in older C# code.

Tip

Remember, the underlying delegate wrapper does not go away; delegate inference just simplifies the syntax a bit by hiding some of it.

Alternatively, you can also set up lambda expressions that take generic type parameters to enable working with generic delegates as you do here in the GenericWay class:

  class GenericWay
    {
                // have a method to create two instances of and call the delegates
                public void WorkItOut( )
                {
                            Func<string,string> dwString = s =>
                            {
                                        Console.WriteLine(s);
                                        return s;
                            };

                            // invoke string delegate
                            string retStr = dwString("Do some generic work");

                            Func<int,int> dwInt = i =>
                            {
                                        Console.WriteLine(i);
                                        return i;
                            };

                            // invoke int delegate
                            int j = dwInt(5);
                }
    }

Discussion

One of the useful things about lambda expressions is the concept of outer variables. The official definition of outer variables is that they are any local variable, value parameter, or parameter array with a scope that contains the lambda expression.

What does this mean? It means that, inside of the code of the lambda expression, you can touch variables outside of the scope of that method. There is a concept of "capturing" the variables that occurs when a lambda expression actually makes reference to one of the outer variables. In the following example, the count variable is captured and incremented by the lambda expression. The count variable is not part of the original scope of the lambda expression but part of the outer scope. It is incremented and then the incremented value is returned and totaled:

  public void SeeOuterWork()
    {
        int count = 0;
        int total = 0;
        Func<int> countUp = () => count++;
        for(int i=0;i<10;i+)
        {
            total += countUp();
        }
        Debug.WriteLine("Total = " + total);
    }

What capturing actually does is extend the lifetime of the outer variable to coincide with the lifetime of the underlying delegate instance that represents the lambda expression. This should encourage you to be careful about what you touch from inside a lambda expression. You could be causing things to hang around a lot longer than you originally planned. The garbage collector won't get a chance to clean up those outer variables until later, when they are used in the lambda expression. Capturing outer variables has another garbage-collector effect: when locals or value parameters are captured, they are no longer considered to be fixed but are now movable, so any unsafe code must now fix that variable before use by using the fixed keyword.

Outer variables can affect how the compiler generates the internal IL for the lambda expression. If it uses outer variables, it is generated as a private method of a nested class rather than as another private method of the class it is declared in, as it otherwise would be. If the outer method is static, then the lambda expression cannot access instance members via the "this" keyword, as the nested class will also be generated as static.

There are two types of lambda expressions: Expression lambdas and Statement lambdas. This Expression lambda has no parameters and simply increments the count variable in an expression:

 int count = 0;
    Count countUp = () => count++;

Statement lambdas have the body enclosed in curly braces and can contain any number of statements like this:

    Func<int,int> dwInt = i =>
    {
                   Console.WriteLine(i);
                   return i;
    };

A few last things to remember about lambda expressions:

  • They can't use break, goto,or continue to jump from the lambda expression to a target outside the lambda expression block.

  • No unsafe code can be executed inside a lambda expression.

  • Lambda expressions cannot be used on the left side of the is operator.

  • Since lambda expressions are a superset of anonymous methods, all restrictions that apply to anonymous methods also apply to lambda expressions.

See Also

The "Lambda Expressions (C# Programming Guide)" topic in the MSDN documentation.

Set Up Event Handlers Without the Mess

Problem

In versions of the .NET Framework prior to 2.0, the System.EventHandler delegate could be used on events in which the arguments were always of type System.EventArgs. This was great if you really didn't care about any data that went along with an event. But as you are all fine programmers and can see the possibilities of passing data along with the event, you had to set up a delegate and an event for every event you wanted. Example 9-7, "Using pre-.NET 2.0 event and event-handling methods" demonstrates an old newspaper class that sends news to subscribers using the pre-.NET 2.0 event and event-handling methodology.

Example 9-7. Using pre-.NET 2.0 event and event-handling methods

public class IWantToKnowThen
{
            public static void TryMe( )
            {
                        OldNewspaper DailyPaperFlash = new OldNewspaper( );
                        DailyPaperFlash.NewsEvent +=
                                    new OldNewspaper.NewsEventHandler(StaleNews);

                        // send news
                        DailyPaperFlash.TransmitStaleNews("Patriots win third super
bowl!");
                        DailyPaperFlash.TransmitStaleNews("W takes office amongst recount.
");
                        DailyPaperFlash.TransmitStaleNews("VS2005 is sooo passe");
            }

            private static void StaleNews(object src, NewsEventArgs nea)
            {
                        Console.WriteLine(nea.LatestNews);
            }
}

// EventArgs derived class to hold our news data
public class NewsEventArgs : EventArgs
{

            private string _latestNews;

            public NewsEventArgs(string latestNews)
            {
                         _latestNews = latestNews;
            }
            public string LatestNews
            {
                        get { return _latestNews; }
            }
}

// OldNewspaper class
public class OldNewspaper
{
    // Allow clients to get the news.
            public delegate void NewsEventHandler(Object sender, NewsEventArgs e);
    public event NewsEventHandler NewsEvent;

    // Provide nice wrapper for sending news to clients.
            public void TransmitStaleNews(string news)

        {
    // Copy to a temporary variable to be thread-safe.
    NewsEventHandler newsEvent = NewsEvent;
    if (newsEvent != null)
        newsEvent(this, new NewsEventArgs(news));
        }
}

This code sets up an event that will report the news to subscribers as it comes in. It passes them the news data as an argument of type NewsEventArgs that has a LatestNews property.

As you can see from this example, whenever you had to set up multiple event handlers, it became an exercise in copy-and-paste and changing the event argument class type over and over again. It would be nice to not have to define lots of delegates and events just to change the event arguments, as all events (and corresponding handlers) are supposed to look like this:

    void [EventHandler](object sender, [EventArgs] args)
    {
         // Do something about this event firing.
    }

Solution

EventHandler<T> takes a type parameter that represents the type of the System.EventArgs derived class to use in your event handlers. The beauty of this is that you no longer have to keep creating a delegate and an event for every event you wish to publish from your class. Even better, the Framework only has to have one event delegate instead of one for every event that passes custom data! Using the example shown in the Problem section, you can now rewrite the declaration of the event handler like this:

  // Old way
    public delegate void NewsEventHandler(Object sender, NewsEventArgs e);
    public event NewsEventHandler NewsEvent;

    // New way
    public event EventHandler<NewsEventArgs> NewsEvent;

Now, you set up the nice wrapper function to allow the user to easily trigger the event:

    // Old way
            public void TransmitNews(string news)
            {
        // Copy to a temporary variable to be thread-safe.
        NewsEventHandler newsEvent = NewsEvent;
        if (newsEvent != null)
            newsEvent(this, new NewsEventArgs(news));
            }
    // New way
            public void TransmitNews(string news)
            {
                        // Copy to a temporary variable to be thread-safe.
                        EventHandler<NewsEventArgs> breakingNews = NewsEvent;
                        if (breakingNews != null)
                                    breakingNews(this, new NewsEventArgs(news));
            }

The client can then hook up to the OldNewspaper class like this:

    // Old way
    public class IWantToKnowThen
    {
                public static void TryMe( )
                {
                            OldNewspaper DailyPaperFlash = new OldNewspaper( );
                            DailyPaperFlash.NewsEvent +=
                                        new OldNewspaper.NewsEventHandler(StaleNews);
                    // send news
                    DailyPaperFlash.TransmitStaleNews("Patriots win third super bowl!");
                    DailyPaperFlash.TransmitStaleNews("W takes office amongst recount.");
                    DailyPaperFlash.TransmitStaleNews("VS2005 is sooo passe");
                }

                private static void StaleNews(object src, NewsEventArgs nea)
                {
                            Console.WriteLine(nea.LatestNews);
                }
    }

    // New way
    public class IWantToKnowNow
    {
                public static void Test( )
                {
                            eNewspaper DailyBitFlash = new eNewspaper( );
                            DailyBitFlash.NewsEvent +=
                                          new EventHandler<NewsEventArgs>(BreakingNews);

                        // send breaking news
                        DailyBitFlash.TransmitBreakingNews("Patriots win!");
                        DailyBitFlash.TransmitBreakingNews("New pres coming in 08.");
                        DailyBitFlash.TransmitBreakingNews("VS2008 & .NET 3.5 Rocks LA");
                }

                private static void BreakingNews(object src, NewsEventArgs nea)
                {
                            Console.WriteLine(nea.LatestNews);
                }
    }

Discussion

The main benefit of using the generic EventHandler instead of System.EventHandler is that you write less code. Being able to declare a generic delegate allows you to have one delegate definition for multiple types. You might ask: Why is this interesting? Previously, when a delegate or event was declared by a class that wanted to publish information and allow multiple client classes to subscribe to it, if any data were to be passed along to the client classes, the convention was that a new class that derived from System.EventArgs had to be created. Then the class would be instantiated, filled with the data, and passed to the client. If the publishing class had only one event to notify people of, this wasn't too bad. If the publishing class had a lot of events, say, like a class derived from a UserControl, there would have to be a separate class derived from System.EventArgs and a separate event defined for every event that needed different data passed to it. Now, with a generic delegate, you can simply declare one delegate/event for each list of parameters you deal with, and then declare the type-specific events you need. Since events are supposed to have this signature:

 void eventname( object sender, System.EventArgs args)

the kind folks at Microsoft gave you System.EventHandler<T> to deal with most events. If your code does have events defined that have more than two parameters, there would need to be a new delegate created to be the base of those events. Since most events do not have more than two parameters, this is a bit nonstandard, but not out of the question.

See Also

The "Generic EventHandler" and "System. EventHandler" topics in the MSDN documentation.

Using Different Parameter Modifiers in Lambda Expressions

Problem

You know you can pass parameters to lambda expressions, but you need to figure out what parameter modifiers are valid with them.

Solution

Lambda expressions can use out and ref parameter modifiers but not the params modifier in their parameter list. However, this does not prevent the creation of delegates with any of these modifiers, as shown here:

  // Declare out delegate.
    delegate int DoOutWork(out string work);

    // Declare ref delegate.
    delegate int DoRefWork(ref string work);

    // Declare params delegate.
    delegate int DoParamsWork(params string[] workItems);

Even though the DoParamsWork delegate is defined with the params keyword on the parameter, it can still be used as a type for a lambda expression, as you'll see in a bit. To use the DoOutWork delegate, create a lambda expression inline using the out keyword and assign it to the DoOutWork delegate instance. Inside the lambda expression body, the out variable s is assigned a value first (as it doesn't have one by definition as an out parameter), writes it to the console, and returns the string hash code. Note that in the parameter list, the type of s (string) must be provided, as it is not inferred for a variable marked with the out keyword. It is not inferred for out or ref variables to preserve the representation at the call site and the parameter declaration site to help the developer clearly reason about the possible assignment to these variables:

   // Declare instance and assign method.
    DoOutWork dow = (out string s) =>
    {
        s = "WorkFinished";
        Console.WriteLine(s);
        return s.GetHashCode( );
    };

To run the lambda expression code, invoke the delegate with an out parameter, and then print out the result to the console:

    // Invoke delegate.
    string work;
    int i = dow(out work);
    Console.WriteLine(work);

To use the ref parameter modifier in a lambda expression, you create an inline method to hook up to the DoRefWork delegate with a ref parameter. In the method, you show you can write the original value out, reassign the value, and get the hash code of the new value. Note that in the parameter list, in the same manner as for the out keyword, the type of s (string) must be provided, as it cannot be inferred for a variable marked with the ref keyword:

 // Declare instance and assign method.
    DoRefWork drw = (ref string s) =>
    {
        Console.WriteLine(s);
        s = "WorkFinished";
        return s.GetHashCode( );
    };

To run the lambda expression, you assign a value to the string work and then pass it as a ref parameter to the DoRefWork delegate that is instantiated. Upon return from the delegate call, you write out the new value for the work string:

   // Invoke delegate.
    work = "WorkStarted";
    i = drw(ref work);
    Console.WriteLine(work);

While it is possible to declare a delegate with the params modifier, you cannot hook up the delegate using a lambda expression with the params keyword in the parameter list. You get the CS1525 Invalid expression term 'params' compiler error on the DoParamsWork line:

   // Done as a lambda expression you get CS1525 "Invalid expression term 'params'"
    DoParamsWork dpw = (params object[] workItems) =>
    //{
    //    foreach (object o in workItems)
    //    {
    //        Console.WriteLine(o.ToString( ));
    //    }
    //    return o.GetHashCode( );
    //};

Even if you try to do this using an anonymous method instead of a lambda expression, you still cannot hook up the delegate with the params keyword in the parameter list. You get the CS1670 "params is not valid in this context" compiler error on the DoParamsWork line:

  // Done as an anonymous method you get CS1670 "params is not valid in this context"
        //DoParamsWork dpw = delegate(params object[] workItems)
        //{
        //    foreach (object o in workItems)
        //    {
        //        Console.WriteLine(o.ToString( ));
        //    }
        //    return o.GetHashCode( );
        //};

You can, however, omit the params keyword and still set up the lambda expression for the delegate, as shown here:

    // All we have to do is omit the params keyword.
    DoParamsWork dpw = workItems =>
    {
        foreach (object o in workItems)
        {
            Console.WriteLine(o.ToString( ));
        }
        return workItems.GetHashCode( );
    };

Notice that although you've removed the params keyword from the lambda expression, this doesn't stop you from using the same syntax. The params keyword is present on the delegate type, so you can invoke it thusly:

  int i = dpw("Hello", "42", "bar");

So this illustrates that you can bind a lambda expression to a delegate declared using params, and once you've done that, you can invoke the lambda expression, passing in any number of parameters you like, just as you'd expect.

Discussion

Lambda expressions cannot access the ref or out parameters of an outer scope. This means any out or ref variables that were defined as part of the containing method are off-limits for use inside the body of the lambda expression:

 // Declare delegate.
    delegate int DoWork(string work);

    public void TestOut(out string outStr)
    {
        // Declare instance.
        DoWork dw = s =>
        {
            Console.WriteLine(s);
            // Causes error CS1628:
            // "Cannot use ref or out parameter 'outStr' inside an
            // anonymous method, lambda expression, or query expression"
            //outStr = s;
            return s.GetHashCode( );
        };
        // Invoke delegate.
        int i = dw("DoWorkMethodImpl1");
    }

    public void TestRef(ref string refStr)
    {
        // Declare instance.
        DoWork dw = s =>
        {
            Console.WriteLine(s);
            // Causes error CS1628:
            // "Cannot use ref or out parameter 'refStr' inside an
            // anonymous method, lambda expression, or query expression"
            // refStr = s;
            return s.GetHashCode( );
        };
        // Invoke delegate
        int i = dw("DoWorkMethodImpl1");
    }

Interestingly enough, lambda expressions can access outer variables with the params modifier:

   // Declare delegate.
    delegate int DoWork(string work);

    public void TestParams(params string[] items)
    {
        // Declare instance.
        DoWork dw = s =>
        {
            Console.WriteLine(s);
            foreach (string item in items)
            {
                Console.WriteLine(item);
            }
            return s.GetHashCode( );
        };
        // Invoke delegate.
        int i = dw("DoWorkMethodImpl1");
    }

Because the params modifier is there for the benefit of the calling site (so the compiler knows to make this a method call that supports variable-length argument lists) and because lambda expressions are never called directly (always called via a delegate), then it makes no sense for an lambda expression to be decorated with something there for the benefit of the calling site-there is no calling site. This is why it doesn't matter that you can't use the params keyword on a lambda expression. For lambda expressions, the calling site is always calling through the delegate, so what matters is whether that delegate has the params keyword or not.

See Also

the section called "Performing Multiple Operations on a List Using Functors"; the "CS1670," "CS1525," "CS1628," "out," "ref," "params," and "System.ParamArrayAttribute" topics in the MSDN documentation.

Using Closures in C#

Problem

You want to associate a small amount of state with some behavior without going to the trouble of building a new class.

Solution

Use lambda expressions to implement closures. Closures can be defined as functions that capture the state of the environment that is in scope where they are declared. Put more simply, they are current state plus some behavior that can read and modify that state. Lambda expressions have the capacity to capture external variables and extend their lifetime, which makes closures possible in C#.

To show an example of this, you will build a quick reporting system that tracks sales personnel and their revenue production versus commissions. The closure behavior is that you can build one bit of code that does the commission calculations per quarter and works on every salesperson.

First, you have to define your sales personnel:

 class SalesWeasel
    {
        #region CTOR
        public SalesWeasel( )
        {
        }

        public SalesWeasel(string name,
                            decimal annualQuota,
                            decimal commissionRate)
        {
            this.Name = name;
            this.AnnualQuota = annualQuota;
            this.CommissionRate = commissionRate;
        }
        #endregion //CTOR

        #region Private Members
        decimal _commission;
        #endregion Private Members

        #region Properties
        public string Name { get; set; }

        public decimal AnnualQuota { get; set; }

        public decimal CommissionRate { get; set; }

        public decimal Commission
        {
            get { return _commission; }
            set
            {
                _commission = value;
                this.TotalCommission += _commission;
            }
       }
       public decimal TotalCommission {get; private set; }
       #endregion // Properties
    }

Sales personnel have a name, an annual quota, a commission rate for sales, and some storage for holding a quarterly commission and a total commission. Now that you have something to work with, let's write a bit of code to do the work of calculating the commissions:

   delegate void CalculateEarnings(SalesWeasel weasel);

    static CalculateEarnings GetEarningsCalculator(decimal quarterlySales,
                                       decimal bonusRate)
        {
             return salesWeasel =>
             {
                 // Figure out the weasel's quota for the quarter.
                 decimal quarterlyQuota = (salesWeasel.AnnualQuota / 4);
                 // Did he make quota for the quarter?
                 if (quarterlySales < quarterlyQuota)
                 {
                     // Didn't make quota, no commission
                     salesWeasel.Commission = 0;
                 }
                 // Check for bonus-level performance (200% of quota).
                 else if (quarterlySales > (quarterlyQuota * 2.0m))
                 {
                     decimal baseCommission = quarterlyQuota *
                     salesWeasel.CommissionRate;
                     weasel.Commission = (baseCommission +
                             ((quarterlySales - quarterlyQuota) *
                             (salesWeasel.CommissionRate * (1 + bonusRate))));
                 }
                 else // Just regular commission
                 {
                     salesWeasel.Commission =
                        salesWeasel.CommissionRate * quarterlySales;
                 }
             };
        }

You've declared the delegate type as CalculateEarnings, and it takes a SalesWeasel. You have a factory method to construct an instance of this delegate for you called GetEarningsCalculator, which creates a lambda expression to do the calculation of the SalesWeasel's commission and returns a CalculateEarnings instantiation.

To get set up, you have to create your SalesWeasels:

 // set up the sales weasels...
    SalesWeasel[] weasels = {
        new SalesWeasel { Name="Chas", AnnualQuota=100000m, CommissionRate=0.10m },
        new SalesWeasel { Name="Ray", AnnualQuota=200000m, CommissionRate=0.025m },
        new SalesWeasel { Name="Biff", AnnualQuota=50000m, CommissionRate=0.001m }};

Then set up the earnings calculators based on quarterly earnings:

    public class QuarterlyEarning
    {
        public string Name { get; set; }
        public decimal Earnings { get; set; }
        public decimal Rate { get; set; }
    }
    QuarterlyEarning[] quarterlyEarnings =
                   { new QuarterlyEarning( ){ Name="Q1", Earnings = 65000m, Rate = 0.1m },
                     new QuarterlyEarning( ){ Name="Q2", Earnings = 20000m, Rate = 0.1m },
                     new QuarterlyEarning( ){ Name="Q3", Earnings = 37000m, Rate = 0.1m },
                     new QuarterlyEarning( ){ Name="Q4", Earnings = 110000m, Rate = 0.
    15m}};

    var calculators = from e in quarterlyEarnings
                      select new
                      {
                          Calculator =
                              GetEarningsCalculator(e.Earnings, e.Rate),
                          QuarterlyEarning = e
                      };

And, finally, run the numbers for each quarter for all SalesWeasels and then you can generate the annual report from this data. This will tell the executives which sales personnel are worth keeping by calling WriteCommissionReport:

  decimal annualEarnings = 0;
    foreach (var c in calculators)
    {
        WriteQuarterlyReport(c.QuarterlyEarning.Name,
            c.QuarterlyEarning.Earnings, c.Calculator, weasels);
        annualEarnings += c.QuarterlyEarning.Earnings;
    }

    // Let's see who is worth keeping...
    WriteCommissionReport(annualEarnings, weasels);

WriteQuarterlyReport invokes the CalculateEarnings lambda expression implementation (eCalc) for every SalesWeasel and modifies the state to assign quarterly commission values based on the commission rates for each one:

    static void WriteQuarterlyReport(string quarter,
                                decimal quarterlySales,
                                CalculateEarnings eCalc,
                                SalesWeasel[] weasels)
    {
        Console.WriteLine("{0} Sales Earnings on Quarterly Sales of {1}:",
            quarter, quarterlySales.ToString("C"));
        foreach (SalesWeasel weasel in weasels)
        {
            // Calc commission
            eCalc(weasel);
            // Report
            Console.WriteLine("      SalesWeasel {0} made a commission of : {1}",

                weasel.Name, weasel.Commission.ToString("C"));
        }
    }

WriteCommissionReport checks the revenue earned by the individual sales personnel against his commission, and if his commission is more than 20 percent of the revenue they generated, you recommend action be taken:

   static void WriteCommissionReport(decimal annualEarnings,
                                    SalesWeasel[] weasels)
    {
        decimal revenueProduced = ((annualEarnings) / weasels.Length);
        Console.WriteLine("");

        Console.WriteLine("Annual Earnings were {0}",
            annualEarnings.ToString("C"));
        Console.WriteLine("");
        var whoToCan = from weasel in weasels
                       select new
                       {
                           // if his commission is more than 20%
                           // of what he produced, can him
                           CanThem = (revenueProduced * 0.2m) <
                                       weasel.TotalCommission,
                           weasel.Name,
                           weasel.TotalCommission
                       };

        foreach (var weaselInfo in whoToCan)
        {
            Console.WriteLine(" Paid {0} {1} to produce {2}",
                weaselInfo.Name,
                weaselInfo.TotalCommission.ToString("C"),
                revenueProduced.ToString("C"));
            if (weaselInfo.CanThem)
            {
                Console.WriteLine("        FIRE {0}!", weaselInfo.Name);
            }
        }
    }

The output for your revenue and commission tracking program is listed here for your enjoyment:

  Q1 Sales Earnings on Quarterly Sales of $65,000.00:
             SalesWeasel Chas made a commission of : $6,900.00
             SalesWeasel Ray made a commission of : $1,625.00
             SalesWeasel Biff made a commission of : $70.25
    Q2 Sales Earnings on Quarterly Sales of $20,000.00:
             SalesWeasel Chas made a commission of : $0.00
             SalesWeasel Ray made a commission of : $0.00
             SalesWeasel Biff made a commission of : $20.00
    Q3 Sales Earnings on Quarterly Sales of $37,000.00:
             SalesWeasel Chas made a commission of : $3,700.00
             SalesWeasel Ray made a commission of : $0.00
             SalesWeasel Biff made a commission of : $39.45
    Q4 Sales Earnings on Quarterly Sales of $110,000.00:
             SalesWeasel Chas made a commission of : $12,275.00
             SalesWeasel Ray made a commission of : $2,975.00
             SalesWeasel Biff made a commission of : $124.63

    Annual Earnings were $232,000.00

        Paid Chas $22,875.00 to produce $77,333.33
            FIRE Chas!
        Paid Ray $4,600.00 to produce $77,333.33
        Paid Biff $254.33 to produce $77,333.33

Discussion

One of the best ways we've heard of to describe closures in C# is to think of an object as a set of methods associated with data and to think of a closure as a set of data associated with a function. If you need to have several different operations on the same data, an object approach may make more sense. These are two different angles on the same problem, and the type of problem you are solving will help you decide which is the right approach. It just depends on your inclination as to which way to go. There are times when one-hundred-percent pure object-oriented programming can get tedious and is unnecessary, and closures are a nice way to solve some of those problems. The SalesWeasel commission example presented here is a demonstration of what you can do with closures. It could have been done without them, but at the expense of writing more class and method code.

Closures have been defined as stated earlier, but there is a stricter definition that essentially implies that the behavior associated with the state should not be able to modify the state in order to be a true closure. We tend to agree more with the first definition, as it defines what a closure should be, not how it should be implemented, which seems too restrictive. Whether you choose to think of this as a neat side feature of lambda expressions or you feel it is worthy of being called a closure, it is another programming trick for your toolbox and should not be dismissed.

See Also

the section called "Performing Multiple Operations on a List Using Functors"; the "Lambda Expressions" topic in the MSDN documentation.

Performing Multiple Operations on a List Using Functors

Problem

You want to be able to perform multiple operations on an entire collection of objects at once, while keeping the operations functionally segmented.

Solution

Use a functor (or function object, as it is also known) as the vehicle for transforming the collection. A functor is any object that can be called as a function. Examples of this are a delegate, a function, a function pointer, or even an object that defines operator() for us C/C++ converts.

Needing to perform multiple operations on a collection is a reasonably common thing in software. Let's say that you have a stock portfolio with a bunch of stocks in it. Your StockPortfolio class would have a List of Stock object and would be able to add stocks:

    public class StockPortfolio : IEnumerable<Stock>
    {
        List<Stock> _stocks;

        public StockPortfolio( )
        {
            _stocks = new List<Stock>( );
        }

        public void Add(string ticker, double gainLoss)
        {
            _stocks.Add(new Stock( ) {Ticker=ticker, GainLoss=gainLoss});
        }

        public IEnumerable<Stock> GetWorstPerformers(int topNumber)
        {
            return _stocks.OrderBy(
                        (Stock stock) => stock.GainLoss).Take(topNumber);
        }

        public void SellStocks(IEnumerable<Stock> stocks)
        {
            foreach(Stock s in stocks)
                _stocks.Remove(s);
        }

        public void PrintPortfolio(string title)
        {
            Console.WriteLine(title);
            _stocks.DisplayStocks( );
        }

        #region IEnumerable<Stock> Members

        public IEnumerator<Stock> GetEnumerator( )
        {
            return _stocks.GetEnumerator( );
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator( )
        {
            return this.GetEnumerator( );
        }

        #endregion
    }

The Stock class is rather simple. You just need a ticker symbol for the stock and its percentage of gain or loss:

   public class Stock
    {
        public double GainLoss { get; set; }
        public string Ticker { get; set; }
    }

To use this StockPortfolio, you add a few stocks to it with gain/loss percentages and print out your starting portfolio. Once you have the portfolio, you want to get a list of the three worst-performing stocks, so you can improve your portfolio by selling them and print out your portfolio again:

    StockPortfolio tech = new StockPortfolio() {
        {"OU81", -10.5},
        {"C#4VR", 2.0},
        {"PCKD", 12.3},
        {"BTML", 0.5},
        {"NOVB", -35.2},
        {"MGDCD", 15.7},
        {"GNRCS", 4.0},
        {"FNCTR", 9.16},
        {"LMBDA", 9.12},
        {"PCLS", 6.11}};

    tech.PrintPortfolio("Starting Portfolio");
    // sell the worst 3 performers
    var worstPerformers = tech.GetWorstPerformers(3);
    Console.WriteLine("Selling the worst performers:");
    worstPerformers.DisplayStocks( );
    tech.SellStocks(worstPerformers);
    tech.PrintPortfolio("After Selling Worst 3 Performers");

So far, nothing terribly interesting is happening. Let's take a look at how you figured out what the three worst performers were by looking at the internals of the GetWorstPerformers method:

   public IEnumerable<Stock> GetWorstPerformers(int topNumber)
    {
        return _stocks.OrderBy(
                    (Stock stock) =>  stock.GainLoss).Take(topNumber);
    }

The first thing you do is make sure the list is sorted so that the worst performing stocks are at the front of the list by calling the OrderBy extension method on IEnumerable<T>. The OrderBy method takes a lambda expression which provides the gain/loss percentage for comparison for the number of stocks indicated by topNumber in the Take extension method.

GetWorstPerformers returns an IEnumerable<Stock> full of the three worst performers. Since they aren't making any money, you should cash in and sell them. For your purposes, selling is simply removing them from the list of stocks in StockPortfolio. To accomplish this, you use yet another functor to iterate over the list of stocks handed to the SellStocks function (the list of worst-performing ones, in your case), and then remove that stock from the internal list that the StockPortfolio class maintains:

  public void SellStocks(IEnumerable<Stock> stocks)
    {
        foreach(Stock s in stocks)
            _stocks.Remove(s);
    }

Discussion

Functors come in a few different flavors that are known as a generator (a function with no parameters), a unary function (a function with one parameter), and a binary function (a function with two parameters). If the functor happens to return a Boolean value, then it gets an even more special naming convention: a unary function that returns a Boolean is called a predicate, and a binary function with a Boolean return is called a binary predicate. You will now notice in the Framework that there are both Predicate<T> and BinaryPredicate<T> delegates defined to facilitate these uses of functors.

The List<T> and System.Array classes take predicates (Predicate<T>, BinaryPredicate<T>), actions (Action<T>), comparisons (Comparison<T>), and converters (Converter<T,U>). This allows these collections to be operated on in a much more general way than was previously possible.

Thinking in terms of functors can be a bit of a challenge at first, but once you put a bit of time into it, you can start to see powerful possibilities open up before you. Any code you can write once, debug once, and use many times is a useful thing, and functors can help you get to that place.

The output for the example is listed here:

  Starting Portfolio
      (OU81) lost 10.5%
      (C#4VR) gained 2%
      (PCKD) gained 12.3%
      (BTML) gained 0.5%
      (NOVB) lost 35.2%
      (MGDCD) gained 15.7%
      (GNRCS) gained 4%
      (FNCTR) gained 9.16%
      (LMBDA) gained 9.12%
      (PCLS) gained 6.11%
    Selling the worst performers:
      (NOVB) lost 35.2%
      (OU81) lost 10.5%
      (BTML) gained 0.5%
    After Selling Worst 3 Performers
      (C#4VR) gained 2%
      (PCKD) gained 12.3%
      (MGDCD) gained 15.7%
      (GNRCS) gained 4%
      (FNCTR) gained 9.16%
      (LMBDA) gained 9.12%
      (PCLS) gained 6.11%

See Also

The "System.Collections.Generic.List<T>," "System.Linq.Enumerable Class," and "System.Array" topics in the MSDN documentation.