0% found this document useful (0 votes)
10 views

Delegates Part 7

The document discusses how delegate chains in .NET work by linking delegate objects together. It explains how to build chains using the Combine method, remove objects from chains using the Remove method, and invoke all delegates in a chain. The GetInvocationList method allows custom invocation of delegates instead of the default serial invocation.

Uploaded by

dean36712
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Delegates Part 7

The document discusses how delegate chains in .NET work by linking delegate objects together. It explains how to build chains using the Combine method, remove objects from chains using the Remove method, and invoke all delegates in a chain. The GetInvocationList method allows custom invocation of delegates instead of the default serial invocation.

Uploaded by

dean36712
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 2

delegate’s return value is discarded.

Your application code will only receive the return value from the
delegate that is at the head of the chain (the last callback method called).
Once constructed, delegate objects are considered to be immutable. That is, delegate objects
always have their _prev fields set to null, and this never changes. When you combine a delegate
object to a chain, Combine internally constructs a new delegate object that has the same _target and
_methodPtr fields as the source object. The _prev field is set to the old head of the chain. The
address of the new delegate object is returned from Combine (see the code in Figure 3).
Now that you know how to build delegate chains, let’s see how to remove a delegate from a
chain. To remove a delegate from a linked-list, you call the Delegate type�s static Remove method,
as shown in Figure 4. The code first builds a chain by constructing two delegate objects, then
combines them into a linked-list by calling the Combine method. Then the Remove method is called.
Remove’s first parameter refers to the head of the delegate object chain and the second parameter
refers to the delegate object that is to be removed from the chain. I know it seems strange to
construct a new delegate object in order to remove it from the chain. To understand why this is
necessary you’ll need some additional explanation.
In the call to Remove, I’m constructing a new delegate object. This delegate object has its _target
and _methodPtr fields initialized appropriately, and the _prev field is set to null. The Remove method
scans the chain (referred to by fbChain), checking if any of the delegate objects in the chain are equal
to the new delegate object. Remember, the overridden Equals method implemented by the Delegate
class compares the _target and _methodPtr fields only and ignores the _prev field.
If a match is found, then the Remove method removes the located delegate object from the
chain by fixing up the previous delegate object’s _prev field. Remove returns the head of the new
chain. If a match is not found, then Remove does nothing (no exception is thrown) and returns the
same value that was passed for its first parameter.
Each call to Remove eliminates only one object from the chain, as demonstrated by the code
in Figure 5.
To make things easier for C# developers, the C# compiler automatically provides overloads of the
+= and -= operators for instances of delegate types. These operators call Delegate.Combine and
Delegate.Remove, respectively. Using these operators simplifies the building of delegate chains. The
C# code in Figure 6 demonstrates how using the C# operators simplifies the code to combine and
remove delegate objects from a chain.
Internally, the compiler translates all uses of += on delegates to calls to Delegate’s Combine
method. Likewise, all uses of the -= operator on delegate objects translate to calls to the Remove
method. In fact, you can build the code I’ve just shown and look at its intermediate language using
ILDasm.exe. This will confirm that the C# compiler did, in fact, replace all += and -= operators with
calls to the Delegate type’s static Combine and Remove methods, respectively.

Invoking a Delegate Chain

At this point, you understand how to build a linked-list chain of delegate objects and how to
invoke all the objects in that chain. All items in the linked-list chain are invoked because the delegate
type’s Invoke method includes code to call the previous delegate (if one exists). This is obviously a
very simple algorithm. While it is good enough for many of the scenarios you may encounter, this
logic has many limitations.
For example, the return values of the callback methods are all discarded, except for the last.
Using this simple algorithm, there is no way to get the return values for all the callback methods
called. But this algorithm has even more limitations. For example, what happens if one of the invoked
delegates throws an exception or blocks for a very long time? Since the algorithm invoked each
delegate in the chain serially, a problem with one of the delegate objects stops all the other
delegates in the chain from getting called. Clearly, this is not a robust algorithm.
For those scenarios where this logic is insufficient, the MulticastDelegate class offers an instance
method, GetInvocationList, that you can use to call each delegate in a chain explicitly, using any
algorithm that meets your needs:

public class MulticastDelegate {


// Creates a delegate array; each item is a clone from the chain
// (NOTE: entry 0 is the tail, which would normally be called first)
public virtual Delegate[] GetInvocationList();
}

The GetInvocationList method operates on a reference to a delegate chain and returns an array
of references to delegate objects. Internally, GetInvocationList walks the specified

You might also like