C# .NET Delegates : Invocation List
Multicast delegates maintain an invocation list, which has an entry for each delegate of the multicast delegate. Entries are added to the invocation list in the same order in which delegates are added. GetInvocationList returns the invocation list as an array of delegates.
This is the syntax of the GetInvocationList method:
-
delegate [] GetInvocationList()
This code retrieves the list of delegates in a multicast delegate, in which each delegate is a wrapper of a function. The name of each function is displayed. The Delegate.Method property returns a MethodInfo type, which encapsulates the function abstracted by the delegate.
using System;
namespace Example.Delegates
{
public delegate void DelegateClass();
public class Program
{
public static void Main()
{
DelegateClass del = (DelegateClass)
DelegateClass.Combine(new DelegateClass[] { MethodA, MethodB, MethodA, MethodB });
del();
foreach (DelegateClass item in del.GetInvocationList())
{
Console.WriteLine(item.Method.Name + " in invocation list.");
}
Console.ReadKey();
}
public static void MethodA()
{
Console.WriteLine("MethodA...");
}
public static void MethodB()
{
Console.WriteLine("MethodB...");
}
}
}
The delegate signature can contain reference parameters. When invoked, the reference is passed to the called functions. Reference parameters are a way for functions on an invocation list to share state. Value parameters are not shareable across the functions. Because the invocation list is called in sequence, beginning with the first delegate and function, each successive entry in the chain can view changes in the reference parameter. The next item in the chain can view those changes and possibly change the state again. In this way, when the multicast delegate is invoked, the state information is propagated along the invocation list. Furthermore, functions in invocation lists that have the same target object or class share the state of the object or class. The following code uses the reference parameter of a multicast delegate as a counter. The delegate has a value and reference parameter. The value parameter is lost between function calls in the invocation list. However, the reference parameter persists.
using System;
namespace Example.Delegates
{
public delegate void DelegateClass(int valCount, ref int refCount);
public class Program
{
public static void Main()
{
DelegateClass del = (DelegateClass)AddOne + (DelegateClass)AddTwo + (DelegateClass)AddOne;
int valCount = 0;
int refCount = 0;
del(valCount, ref refCount);
Console.WriteLine("Value count = {0}", valCount); // 0
Console.WriteLine("Reference count = {0}", refCount); // 4
Console.ReadKey();
}
public static void AddOne(int valCount, ref int refCount)
{
++valCount;
++refCount;
}
public static void AddTwo(int valCount, ref int refCount)
{
valCount += 2;
refCount += 2;
}
}
}
You can access the invocation list to execute each delegate and function therein directly. There are two reasons to invoke the invocation list directly. First, invoke the delegates explicitly to obtain the return of each delegate. When the invocation list is invoked implicitly, only the return of the last function is garnered. Second, invoke the invocation list directly in special circumstances (for example, to modify how exceptions are handled in a multicast delegate, which is described later).
The following code uses the invocation list to calculate a factorial. The Incrementer method increments a number, which is a reference parameter. The incremented value is returned from the method. Five delegates are created and initialized with the Increment method and combined into a multicast delegate. The foreach loop iterates the invocation list, multiplying the results of each function to calculate a factorial.
using System;
namespace Example.Delegates
{
public delegate int IncrementDelegate(ref short refCount);
public class Program
{
public static void Main()
{
IncrementDelegate[] values = { Incrementer, Incrementer, Incrementer, Incrementer, Incrementer };
IncrementDelegate del = (IncrementDelegate)IncrementDelegate.Combine(values);
long result = 1;
short count = 1;
foreach (IncrementDelegate number in del.GetInvocationList())
{
result = result * number(ref count);
}
Console.WriteLine("{0} factorial is {1}", del.GetInvocationList().Length, result);
Console.ReadKey();
}
public static int Incrementer(ref short refCount)
{
return refCount++;
}
}
}
-
Archives
- February 2009 (1)
- November 2008 (6)
- October 2008 (4)
- September 2008 (13)
- August 2008 (11)
- July 2008 (29)
- June 2008 (19)
- May 2008 (8)
-
Categories
-
RSS
Entries RSS
Comments RSS

