0% found this document useful (0 votes)
38 views3 pages

Delegates Part 10

The document discusses how delegate chains work in .NET. Delegate objects can be combined into linked lists called chains, where each delegate in the chain invokes the next. Methods like Combine are used to link delegates together, while Remove removes a delegate from the chain. The C# language simplifies working with chains using operators like += and -=

Uploaded by

dean36712
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
38 views3 pages

Delegates Part 10

The document discusses how delegate chains work in .NET. Delegate objects can be combined into linked lists called chains, where each delegate in the chain invokes the next. Methods like Combine are used to link delegates together, while Remove removes a delegate from the chain. The C# language simplifies working with chains using operators like += and -=

Uploaded by

dean36712
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 3

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.
accessibility (§15.3.6), the new (§15.3.5), static (§15.6.3, §15.8.4), virtual (§15.6.4, §15.8.5),
override (§15.6.5, §15.8.5), sealed (§15.6.6), abstract (§15.6.7, §15.8.5), and extern (§15.6.8)
modifiers.

Event declarations are subject to the same rules as method declarations (§15.6 – p. 394) with
regard to valid combinations of modifiers.

The type of an event declaration shall be a delegate_type (§8.2.8 – p. 73; p. 517), and that
delegate_type shall be at least as accessible as the event itself (§7.5.5).

An event declaration can include event_accessor_declarations. However, if it does not, for non-
extern, non-abstract events, the compiler shall supply them automatically (§15.8.2); for extern
events, the accessors are provided externally.

An event declaration that omits event_accessor_declarations defines one or more events—one


for each of the variable_declarators. The attributes and modifiers apply to all of the members
declared by such an event_declaration.

It is a compile-time error for an event_declaration to include both the abstract modifier and
event_accessor_declarations.

When an event declaration includes an extern modifier, the event is said to be an external
event. Because an external event declaration provides no actual implementation, it is an error
for it to include both the extern modifier and event_accessor_declarations.

It is a compile-time error for a variable_declarator of an event declaration with an abstract or


external modifier to include a variable_initializer.

An event can be used as the left operand of the += and -= operators. These operators are used,
respectively, to attach event handlers to, or to remove event handlers from an event, and the
access modifiers of the event control the contexts in which such operations are permitted.

The only operations that are permitted on an event by code that is outside the type in which that
event is declared, are += and -=. Therefore, while such code can add and remove handlers for
an event, it cannot directly obtain or modify the underlying list of event handlers.

In an operation of the form x += y or x –= y, when x is an event the result of the operation has
type void (§12.21.5) (as opposed to having the type of x, with the value of x after the
assignment, as for other the += and -= operators defined on non-event types). This prevents
external code from indirectly examining the underlying delegate of an event.

Example:
The following example shows how event handlers are attached to instances of the Button class:

public delegate void EventHandler(object sender, EventArgs e);

public class Button : Control


{
public event EventHandler Click;
}

public class LoginDialog : Form


{
Button okButton;
Button cancelButton;

public LoginDialog()
{
okButton = new Button(...);
okButton.Click += new EventHandler(OkButtonClick);
cancelButton = new Button(...);
cancelButton.Click += new EventHandler(CancelButtonClick);
}

void OkButtonClick(object sender, EventArgs e)


{
// Handle okButton.Click event
}

void CancelButtonClick(object sender, EventArgs e)


{
// Handle cancelButton.Click event }
}
}

Here, the LoginDialog instance constructor creates two Button instances and attaches event
handlers to the Click events.
end example

You might also like