2004-03-08
| Table of Contents: |
| Rate This Article: | Add This Article To: |
( Page 4 of 6 )
Invoking Multiple Delegates
Among the things you can do with delegates is invoke several of them, all at the same time. Delegates have internal storage, called an invocation list, that holds multiple other delegates. Listing 3 demonstrates how to invoke multiple delegates at the same time.
Listing 3. MultipleDelegatesViaDelegates.cs
// displays a report by invoking all selected delegates
public void DoReport(double units, UnitConversion conversions)
{
Console.WriteLine("\nCONVERSION REPORT\n");
// 4. invoke all delegates synchronously and in order
conversions(units);
Console.WriteLine();
}
static void Main()
{
MultipleDelegatesViaDelegates dels = new MultipleDelegatesViaDelegates();
double units;
int[] conversionTypes;
dels.GetUserInput(out units, out conversionTypes);
UnitConversion conversions = null;
foreach (int conversionType in conversionTypes)
{
// 3. get delegate instances via factory method.
conversions += dels.GetConversionMethod(conversionType);
}
dels.DoReport(units, conversions);
Console.ReadLine();
}
In Listing 3, the Main method retrieves a conversionTypes array from the GetUserInput method and iterates through each conversion type, adding each delegate returned from GetConversionMethod to the conversions delegate invocation list.
Most of the time, when invoking multiple delegates, the handler methods will be defined to return type void. This is because when they are invoked, only the last delegate in the list will return the value, which has few benefits, if any. If you need to capture results from each handler method, it's best to set up a collection or some other state object where the results could be recorded and retrieved after the delegate invocation completes.
Adding and Removing DelegatesNotice how Listing 3 uses the += syntax when adding delegates to the conversions delegate's invocation list. This is equivalent to the following:
// 3. get delegate instances via factory method. conversions = conversions + dels.GetConversionMethod(conversionType);
You can add multiple delegates with the + operator. The following code shows another way to do this (assuming 3 conversion options were chosen by the user):
conversions =
dels.GetConversionMethod(conversionTypes[0]) +
dels.GetConversionMethod(conversionTypes[1]) +
dels.GetConversionMethod(conversionTypes[2]);
You can also remove delegates with the -= operator. Here's one way to do it:
conversions -= dels.GetConversionMethod(conversionTypes[0]);
conversions -= dels.GetConversionMethod(conversionTypes[1]);
conversions -= dels.GetConversionMethod(conversionTypes[2]);
Here's another way to remove the delegates that is more explicit:
conversions -= new UnitConversion(dels.FeetToInches);
conversions -= new UnitConversion(dels.YardsToInches);
conversions -= new UnitConversion(dels.CentimetersToInches);
Additionally, you could use the original delegate instance to remove it from the invocation list. However, it would be wasteful to have extra delegates taking up space in your code just for this purpose. Notice, in the code above, that the new UnitConversion instantiation will remove a delegate from the conversions delegate list. If there happened to be two of the same delegate added to a delegate, then the last delegate of the type added would be the first to be removed.
When a delegate is invoked, all of its constituent delegates are invoked synchronously in the same order that they were added. To observe this behavior, run the code in Listing 3, keep track of the order in which you select conversions, and notice how the report always prints results in that order.
Another tip is to protect against the case where no constituent delegates have been added to a delegates invocation list. Before a delegate is instantiated or a delegate is assigned, its value is null. Invoking a null delegate causes a NullReferenceException exception to be thrown. You can see this by running the code in Listing 3 and selecting "Q" without selecting any other options. To deal with this, replace the raw delegate invocation in the DoReport method with the following code:
if (conversions != null)
{
conversions(units);
}
else
{
Console.WriteLine("No Conversions Selected.");
}
Doing so allows the code to handle the null condition gracefully, and ensures that an exception is not raised.
![]() |
|


