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.
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(" Output: " + 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); } }
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 Recipe 7.1 and Recipe 7.3; see the “Delegate Class” and “Delegate.GetInvocationList Method” topics in the MSDN documentation.