Module 8: Delegates and Events |
11 |
|
|
|
This code generates the following output:
Before flipping, the switch is: Down Flipping switch ...
... bathroom light is on
After flipping, the switch is: Up
Before flipping, the switch is: Up Flipping switch ...
... bathroom light is off
After flipping, the switch is: Down
Before flipping, the switch is: Down Flipping switch ...
... bedroom light is on
After flipping, the switch is: Up
Before flipping, the switch is: Up Flipping switch ...
... bedroom light is off
After flipping, the switch is: Down
12 |
Module 8: Delegates and Events |
Topic Objective
To provide an overview of the topics in this section.
Lead-in
If you change the state in one object, you may need to broadcast that change to multiple objects.
!Multicast Delegate Scenario
!Single vs. Multicast Delegates
!Creating and Invoking Multicast Delegates
!C# Language-Specific Syntax
!Delegate Details
*****************************ILLEGAL FOR NON-TRAINER USE******************************
For Your Information
As noted in the C# Language-Specific Syntax in this module, delegate types with a void return value in C# cause the compiler to derive the delegate class from the MulticastDelegate class.
If you change the state in one object, you may need to broadcast that change to multiple objects. You can use multicast delegate objects to provide this functionality; they can be composed together so that a single invocation invokes all of their methods, just as a single light switch can turn on or off all lights connected to that switch.
Module 8: Delegates and Events |
13 |
|
|
|
Multicast Delegate Scenario
Topic Objective
To illustrate the typical multicast delegate use by using the common scenario of a switch that controls two light bulbs.
Lead-in
The following scenario of a switch that controls two lights illustrates the use of multicast delegates.
|
|
4 - OnFlipCallback method |
1 - Change in |
Switch Object |
changes light1’s state |
switch position |
|
invokes switch’s |
|
Light1 Object |
OnFlip method |
|
|
Light2 Object
|
OnFlip method |
OnFlipCallback |
|
|
|
method |
OnFlipCallback |
2 - OnFlip method |
|
|
3 - delegate1 invokes |
method |
invokes multicast |
|
delegate1 |
light1’s OnFlipCallback |
7 - OnFlipCallback |
|
|
|
|
Invocation list |
|
method changes |
|
|
light2’s state |
|
Multicast delegate1 object |
|
|
|
|
|
Multicast delegate1 object |
|
|
5 - delegate2 |
Multicast delegate2 object |
6 - delegate2 invokes |
is invoked |
Multicast delegate2 object |
light2’s OnFlipCallback |
|
*****************************ILLEGAL FOR NON-TRAINER USE******************************
To run the build slide, click through the lower-left button on the slide.
The following scenario of a switch that controls two lights illustrates the use of multicast delegates. The switch object models the light switch, and the two light objects model the two electric lights. To provide the capability to dynamically connect, disconnect, and reconnect light object methods to the switch object, the switch object is dynamically connected to the light objects by instantiating and composing two multicast delegate objects.
In the light scenario, multicast delegate1 refers to the light1 object’s
OnFlipCallback method, and multicast delegate2 refers to the light2 object’s
OnFlipCallback method. Their composition logically represents an invocation list, a list of methods that are executed when the delegate is invoked. In this case, the invocation list consists of these two methods.
In the light switch scenario shown in the slide, the multicast delegate objects encapsulate references to two objects and two methods. When the switch is flipped:
1.The switch object’s OnFlip method is invoked.
2.The OnFlip method invokes the multicast delegate1 object.
3.The multicast delegate1 object first invokes the light1 object’s
OnFlipCallback method.
4.The light1 object’s OnFlipCallback method changes the state of the light1 object.
5.The multicast delegate1 object next invokes the multicast delegate2 object.
6.The multicast delegate2 object invokes the light2 object’s
OnFlipCallback method.
7.The light2 object’s OnFlipCallback method changes the state of the light2 object.
You can compose additional multicast delegates to allow the switch to control additional lights.
14 |
Module 8: Delegates and Events |
Single vs. Multicast Delegates
Topic Objective
To explain the difference between single-cast and multicast delegates.
Lead-in
When delegate declarations are compiled, the compiler generates a new class, which derives from two delegate classes provided by the .NET Framework.
!All Delegates Have an Invocation List of Methods That Are Executed When Their Invoke Method is Called
!Single-Cast Delegates: Derived Directly From System.MulticastDelegate
#Invocation list contains only one method
!Multicast Delegates: Derived from System.MulticastDelegate
#Invocation list may contain multiple methods
#Multicast delegates contain two static methods to add and remove references from invocation list: Combine and Remove
!Use GetInvocationList to Obtain an Invocation List as an Array of Delegate References
!Use a Delegate’s Target and Method Properties to Determine:
#Which object will receive the callback
#Which method will be called
*****************************ILLEGAL FOR NON-TRAINER USE******************************
When delegate declarations are compiled, the compiler, in effect, generates a new class. The new delegate class derives from the System.MulticastDelegate class that is provided by the .NET Framework.
All delegates have an invocation list, or linked list of delegates that are executed when the invoke method is called. A delegate that derives from the MulticastDelegate class may contain an invocation list with multiple delegates.
The MulticastDelegate class contains two static methods to add and remove method references from an invocation list: Combine and Remove.
Combine is declared as follows:
public static Delegate Combine( Delegate a,
Delegate b);
The method returns a new multicast Delegate object with an invocation list that concatenates the invocation lists of a and b in that order.
Remove is declared as follows:
public static Delegate Remove( Delegate source,
Delegate value);
The method returns a new Delegate object with an invocation list formed by taking the invocation list of source and removing the last occurrence of value, if value is found in the invocation list of source. If value is null or if value is not found, then source is returned.
You can use the method GetInvocationList to obtain the invocation list as an array of delegate references. You can also use the delegate’s Target and Method properties to determine which object is to receive the callback and which method is to be called. In the case of a static method, Target is null.
Module 8: Delegates and Events |
15 |
|
|
|
Creating and Invoking Multicast Delegates
Topic Objective
To provide specific examples of how to create and invoke multicast delegates, and how to iterate though an invocation list to invoke specific delegates.
Lead-in
This sample code shows how to create and invoke multicast delegates, and how to iterate through an invocation list to invoke specific delegates.
// assign to c the composition of delegates a and b // assign to c the composition of delegates a and b c = (MyDelegate2)Delegate.Combine(a, b);
c = (MyDelegate2)Delegate.Combine(a, b);
// assign to d the result of removing a from c // assign to d the result of removing a from c d = (MyDelegate2)Delegate.Remove(c, a);
d = (MyDelegate2)Delegate.Remove(c, a);
// Iterate through c's invocation list // Iterate through c's invocation list // and invoke all delegates except a // and invoke all delegates except a
Delegate[] DelegateList = c.GetInvocationList(); Delegate[] DelegateList = c.GetInvocationList(); for (int i = 0; i < DelegateList.Length; i++) { for (int i = 0; i < DelegateList.Length; i++) { if (DelegateList[i].Target != aFoo1) {
if (DelegateList[i].Target != aFoo1) { ((MyDelegate2) DelegateList[i])(); ((MyDelegate2) DelegateList[i])();
}}
}}
*****************************ILLEGAL FOR NON-TRAINER USE******************************
The following sample code shows:
!How to create multicast delegate objects.
!How to write code to invoke delegates’ Combine and Remove methods.
!How to write code to iterate through an invocation list invoking all delegates, except those delegates whose target is a specific object.
16 |
Module 8: Delegates and Events |
using System;
public delegate void MyDelegate2();
public class Foo
{
public void Bar() { Console.WriteLine("Bar invoked");
}
}
class Application {
public static void Main() { Foo aFoo1 = new Foo(); Foo aFoo2 = new Foo();
MyDelegate2 a, b, c, d;
a = new MyDelegate2(aFoo1.Bar); b = new MyDelegate2(aFoo2.Bar);
//assign to delegate c the composition of delegates a and b c = (MyDelegate2)Delegate.Combine(a , b);
//assign to d the result of removing a from c
d = (MyDelegate2)Delegate.Remove(c , a);
//iterate through c's invocation list
//and invoke all delegates except those that target aFoo1 Delegate[] DelegateList = c.GetInvocationList();
for (int i = 0; i < DelegateList.Length; i++) {
if (DelegateList[i].Target != aFoo1) { ((MyDelegate2) DelegateList[i])();
}
}
}
}
The preceding code invokes the delegate that invokes object aFoo2’s Bar method and outputs:
Bar invoked
Module 8: Delegates and Events |
17 |
|
|
|
C# Language-Specific Syntax
Topic Objective
To present helpful alternative C# syntax.
Lead-in
Delegate types with a void return value in C# cause the compiler to derive the delegate class from the
MulticastDelegate class.
!C# Delegates That Return Void Are Multicast Delegates
!In C#, Use the + and - Operators to Add and Remove Invocation List Entries
#Less verbose than Combine and Remove methods
|
MyDelegate a, b, c, d; |
|
|
|
|
MyDelegate a, b, c, d; |
|
|
a = new |
MyDelegate(Foo); |
|
|
a = new |
MyDelegate(Foo); |
|
|
b = new |
MyDelegate(Bar); |
|
|
b = new |
MyDelegate(Bar); |
|
|
c = a + |
b; |
// Compose two delegates to make another |
|
|
c = a + |
b; |
// Compose two delegates to make another |
|
|
d = c - |
a; |
// Remove a from the composed delegate |
|
|
d = c - |
a; |
// Remove a from the composed delegate |
|
|
a += b; |
|
// Add delegate b to a's invocation list |
|
|
a += b; |
|
// Add delegate b to a's invocation list |
|
|
a -= b; |
|
// Remove delegate b from a's list |
|
|
a -= b; |
|
// Remove delegate b from a's list |
|
*****************************ILLEGAL FOR NON-TRAINER USE******************************
Delegate types with a void return value in C# cause the compiler to derive the delegate class from the MulticastDelegate class. You can also use these delegates’ addition operator (+) and the subtraction operator (-) to invoke the Combine and Remove methods for delegate composition and decomposition.
18 |
Module 8: Delegates and Events |
Demonstration: Multicast Delegates
Topic Objective
To demonstrate how to use the + and – operators to add and remove methods.
Lead-in
You can add and remove methods from the invocation list of multicast delegates by using the + and – operators.
*****************************ILLEGAL FOR NON-TRAINER USE******************************
Delivery Tip
Use Visual Studio .NET to run this code. Set breakpoints or single-step to illustrate the sequence of events.
In this demonstration, you will learn how to add and remove methods from the invocation list of multicast delegates by using the + and – operators.
using System;
namespace Multicast_Delegates
{
delegate void MyDelegate3(string s);
class MyClass
{
public static void Hello(string s) { Console.WriteLine(" Hello, {0}!", s);
}
public static void Goodbye(string s) { Console.WriteLine(" Goodbye, {0}!", s);
}
(Code continued on the following page.)
|
Module 8: Delegates and Events |
19 |
public static void Main() { |
|
|
MyDelegate3 a, b, c, d; |
|
|
a = new MyDelegate3(MyClass.Hello); |
|
|
b = new MyDelegate3(MyClass.Goodbye); |
|
|
c = a + b; |
// Compose two delegates to make another |
|
|
d = c - a; |
// Remove a from c to make another |
|
|
Console.WriteLine("Invoking delegate a:"); a("A");
Console.WriteLine("Invoking delegate b:"); b("B");
Console.WriteLine("Invoking delegate c:"); c("C");
Console.WriteLine("Invoking delegate d:"); d("D");
Console.WriteLine("Adding b to a and invoking:");
a += b; |
// Add the b delegate to a |
a("E"); |
|
Console.WriteLine("Removing b from a and invoking:");
a -= b; |
// Remove the b delegate from a |
a("F"); |
|
}
}
}
This code generates the following output:
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
Adding b to a and invoking:
Hello, E!
Goodbye, E!
Removing b from a and invoking:
Hello, F!
};
};
20 |
Module 8: Delegates and Events |
Delegate Details
Topic Objective
To show how a delegate declaration is handled by the compiler.
Lead-in
When delegate declarations are compiled, the compiler generates a new class that derives from
System.Delegate.
!A Delegate Declaration Causes the Compiler to Generate a New Class
//delegate void MyDelegate3(string val);
//delegate void MyDelegate3(string val);
class MyDelegate3 : System.MulticastDelegate {
class MyDelegate3 : System.MulticastDelegate {
public MyDelegate3(object obj, methodref mref)
public MyDelegate3(object obj, methodref mref)
: base (obj, mref) { //...
: base (obj, mref) { //...
}}
public void virtual Invoke(string val) { //...
public void virtual Invoke(string val) { //...
}}
*****************************ILLEGAL FOR NON-TRAINER USE******************************
For Your Information
There is no actual type named methodref, but having an instance of a type that encapsulates a reference to a class method resembles what the compiler actually does.
As previously noted in this module, when delegate declarations are compiled, the compiler, in effect, generates a new class that derives from System.Delegate. The new delegate class has two members: a constructor and an Invoke method. The following class declaration resembles what the compiler actually does:
// delegate void MyDelegate3(string val);
class MyDelegate3 : System.MulticastDelegate { public MyDelegate3(object obj, methodref mref)
: base (obj, mref) {//...
}
public void virtual Invoke(string val) {//...
}
}
The first member is a constructor: its first parameter is the delegate’s target object, and its second parameter is a reference to a method. When a delegate refers to a static method, the target object is null.
The Invoke method for the class MyDelegate3 indicates that delegate instances of this class encapsulate methods that have a void return and a single string parameter. When a delegate is invoked, the Invoke method is called with the specified parameters.