DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 7.2 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, whose return value is returned to the calling application. You need to be able to access the return value of each delegate that is fired in the multicast delegate.

Solution

Use the GetInvocationList method as in Recipe 7.1. This method returns each individual delegate from a multicast delegate. In doing so, we 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 void TestIndividualInvokesRetVal( )
{
    MultiInvoke MI1 = new MultiInvoke(TestInvoke.Method1);
    MultiInvoke MI2 = new MultiInvoke(TestInvoke.Method2);
    MultiInvoke MI3 = new MultiInvoke(TestInvoke.Method3);

    MultiInvoke All = MI1 + MI2 + MI3;

    int retVal = -1;

    Console.WriteLine("Invoke individually (Obtain each return value):");
    foreach (MultiInvoke individualMI in All.GetInvocationList( ))
    {
        retVal = individualMI( );
        Console.WriteLine("\tOutput: " + retVal);
    }
}

The following delegate defines the MultiInvoke delegate:

public delegate int MultiInvoke( );

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

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

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

    public static int Method3( )
    {
        Console.WriteLine("Invoked Method3");
        return (3);
    }
}

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 All delegate was invoked normally, as in the following code:

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

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

By using the GetInvocationList method of the MulticastDelegate class, we 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, we can retrieve each return value from each fired delegate. (More information on the GetInvocationList method is presented in Recipe 7.1.)

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 TestIndividualInvokesRetVal, presented in this recipe. To better handle this situation, see Recipe 7.3.

See Also

See Recipe 7.1 and Recipe 7.3; see the "Delegate Class" and "Delegate.GetInvocationList Method" topics in the MSDN documentation.

    [ Team LiB ] Previous Section Next Section