10.4 The Simplest Possible Delegate Example10.5 Retrofiting the Car Type with Delegates 10.6 A more Elaborate Delegate Example 3... Microsoft Roadmap 10.7 Understanding Delegate Covaranc
Trang 1Chapter 10
Delegates,Events, and Lambdas
Hoang Anh Viet
VietHA@it-hut.edu.vn
HaNoi University of Technology
1
Trang 310.4 The Simplest Possible Delegate Example
10.5 Retrofiting the Car Type with Delegates
10.6 A more Elaborate Delegate Example
3
Trang 4Microsoft
Roadmap
10.7 Understanding Delegate Covarance
10.8 Greating Generic Delegates
10.9 Understanding C# Events.
10.10 The Generic C# EventHandler<T> Delegate.
10.11 Understanding C# Anonymouns Methods
10.12 Understanding Method Group Conversions
10.13 The C# 2008 Lambdas Operator.
4
Trang 5Microsoft
10.1 Understanding the NET Delegate Type
A delegate is a type that references a method.
Once a delegate is assigned a method, it behaves exactly like that method
The delegate method can be invoked like any other
method, with parameters and a return value.
Such as :
5
public delegate int PerformCalculation( int x, int y);
Trang 6Microsoft
Kinds of Methods
Any method from any accessible class or struct that
matches the delegate's signature, which consists of the return type and parameters, can be assigned to the
delegate
The method can be either static or an instance method
Note :
• In the context of method overloading:
The signature of a method does not include the return value.
• In the context of delegates:
The signature does include the return value
Trang 7Microsoft
Delegates Overview
• Delegates are like C++ function pointers but are type safe.
• Delegates allow methods to be passed as
parameters
• Delegates can be used to define callback methods
• Delegates can be chained together; for example,
multiple methods can be called on a single event.
• Methods do not have to match the delegate signature exactly
• Allow code blocks to be passed as parameters in
place of a separately defined method.
Trang 8Microsoft
Efficency of Delegates
Plug new code into existing classes.
Makes it possible to programmatically change method calls.
Defines callback methods Allows for an algorithm to be written in a more general way
Trang 910.4 The Simplest Possible Delegate Example
10.5 Retrofiting the Car Type with Delegates
10.6 A more Elaborate Delegate Example
9
Trang 11public delegate void Del<T>(T item);
public void Notify(int i) { }
Del<int> d1 = new Del<int>(Notify);
Del<int> d2 = Notify;
Trang 12public delegate void ProcessBookDelegate(Book book);
// Print the title of the book.
static void PrintTitle(Book b) { // ;};
Trang 13 The - operator can be used to remove a component
delegate from a composed delegate
Constraint:
Trang 14delegate void Del(string s);
static void Goodbye(string s)
{
System.Console.WriteLine( " Goodbye, {0}!", s);
Trang 15// Create the delegate object b that references
// the method Goodbye:
b = Goodbye;
// The two delegates, a and b, are composed to form c:
c = a + b;
// Remove a from the composed delegate, leaving d,
// which calls only the method Goodbye:
Trang 1610.4 The Simplest Possible Delegate Example
10.5 Retrofiting the Car Type with Delegates
10.6 A more Elaborate Delegate Example
16
Trang 17Microsoft
10.3 The System.MulticastDelegate and System.Delegate Base class.
The System.MulticastDelegate
System.Delegate Base class
Trang 18• MulticastDelegate is a special class.
• Compilers and other tools can derive from this class
• But we cannot derive from it explicitly
[SerializableAttribute]
[ComVisibleAttribute(true)] public abstract class MulticastDelegate : Delegate
Trang 20Microsoft
Delegate Class
• The Delegate class is the base class for delegate types.
• Only the system and compilers can derive explicitly from the Delegate class or from the Multicast.Delegate class.
• Don’t permit to derive a new type from a delegate type.
• The Delegate class is not considered a delegate type; it is a class used to derive delegate types.
• Most languages implement a delegate keyword, and
compilers for those languages are able to derive from the Multicast.Delegate class
Trang 21Microsoft
References of a delegate type
A delegate is an instance of a delegate type that has
references to:
• An instance method of a type and a target object
assignable to that type
• An instance method of a type, with the hidden this
parameter exposed in the formal parameter list The delegate is said to be an open instance delegate
Trang 22Microsoft
Invocation list of a delegate
It is an ordered set of delegates in which each element of the list invokes exactly one of the methods represented
by the delegate.
An invocation list can contain duplicate methods.
Methods are invoked in the order in which they appear in the invocation list.
A delegate attempts to invoke every method in its
invocation list.
Delegates are immutable; once created, the invocation list of a delegate does not change.
Trang 23Microsoft
References to a static method
The delegate which references to a static method stores a reference to the method's entry point.
When a delegate represents a static method closed over its first argument, it stores
• A reference to the method's entry point and
• A reference to a target object assignable to the type of the method's first argument
When the delegate is invoked, the first argument of the static method receives the target object.
Trang 2410.4 The Simplest Possible Delegate Example
10.5 Retrofiting the Car Type with Delegates
10.6 A more Elaborate Delegate Example
24
Trang 25 Here is the complete code, with analysis to follow:
Trang 26namespace SimpleDelegate
{
// This delegate can point to any method,
// taking two integers and returning an integer.
public delegate int BinaryOp( int x, int y);
// This class contains methods BinaryOp //will // point to.
public class SimpleMath
Trang 27// Create a BinaryOp object that
// "points to" SimpleMath.Add().
BinaryOp b = new BinaryOp(SimpleMath.Add);
// Invoke Add() method indirectly using //delegate object Console.WriteLine( "10 + 10 is {0}", b(10, 10));
Console.ReadLine();
}
} //end of class program.
}//end of the namespace SimpleDelegate.
Example
Trang 28Microsoft
Some Analyses.
To insert the target method to a given delegate, simply pass
in the name of the method to the delegate’s constructor.
At this point, we are able to invoke the member pointed to using a syntax that looks like a direct function invocation:
The runtime actually calls the compiler-generated Invoke() method.
C# does not require Invoke() call within your code base, that
is free.
// Invoke() is really called here!
Console.WriteLine( "10 + 10 is {0}", b(10, 10));
Trang 29Microsoft
Some Analyses.
The following code statement is permissible:
Recall that NET delegates are type safe.
attempt to pass a delegate a method that does not
“match the pattern,”, receive a compile-time error.
// Error! Method does not match delegate pattern!
BinaryOp b2 = new BinaryOp(SimpleMath.SquareNumber);
Trang 3010.4 The Simplest Possible Delegate Example
10.5 Retrofiting the Car Type with Delegates
10.6 A more Elaborate Delegate Example
30
Trang 31Microsoft
10.5 Retrofitting The Car Type With
Delegate
Here are the basic steps we will need to take:
• Define new delegate types that will send notifications
to the caller.
• Declare a member variable of these delegate types in the Car class.
• Create helper functions on the Car that allow the
caller to set the methods maintained by the delegate member variables.
• Update the Accelerate() method to invoke the
delegate’s invocation list under the correct circumstances.
Trang 32// Define the delegate types.
public delegate void AboutToBlow( string msg);
public delegate void Exploded ( string msg);
// Define member variables of each delegate type.
private AboutToBlow almostDeadList;
private Exploded explodedList;
// Add members to the invocation lists using helper methods.
public void OnAboutToBlow( AboutToBlow clientMethod)
Trang 33(OnAboutToBlow() and OnExploded()), that allow the
client to add a method to the delegate’s invocation list.
Trang 34Microsoft
Updating the Accelerate() method
we need to update the Accelerate() method to invoke each
delegate, rather than iterate over an ArrayList of client-side sinks
public void Accelerate(int delta)
{
// If the car is dead, fire Exploded event.
if (carIsDead) {
if (explodedList != null) explodedList( "Sorry, this car is dead ");
}
Trang 36Microsoft
Remark
Before we invoke the methods maintained by the
almostDeadList and explodedList member variables, we are checking them against a null value.
If the caller does not call the OnAboutToBlow() and
OnExploded() helper methods, and we attempt to invoke the delegate’s invocation list, we will trigger a
NullReferenceException and bomb at runtime.
Observe the updates to the Program class:
Trang 37Car c1 = new Car( "SlugBug", 100, 10);
// Register event handlers with Car type.
c1.OnAboutToBlow( new Car.AboutToBlow(CarAboutToBlow)); c1.OnExploded(new Car.Exploded(CarExploded));
// Speed up (this will trigger the events).
// The Car will call these methods.
public static void CarAboutToBlow(string msg)
Trang 38 To enable multicasting on the Car type, we could update the OnAboutToBlow() and OnExploded() methods.
Trang 39Microsoft
Add multiple methods to a delegate
{
// Add member to the invocation lists.
public void OnAboutToBlow(AboutToBlow clientMethod) { almostDeadList += clientMethod; }
public void OnExploded(Exploded clientMethod)
{ explodedList += clientMethod; }
}
Trang 40Console.WriteLine( "***** Delegates as event enablers *****\n");
Car c1 = new Car( "SlugBug", 100, 10);
// Register multiple event handlers!
c1.OnAboutToBlow( new Car.AboutToBlow(CarAboutToBlow));
c1.OnAboutToBlow(new Car.AboutToBlow(CarIsAlmostDoomed));
c1.OnExploded(new Car.Exploded(CarExploded));
}
// Car will call these.
public static void CarAboutToBlow(string msg)
{ Console.WriteLine(msg); }
public static void CarIsAlmostDoomed(string msg)
{ Console.WriteLine( "Critical Message from Car: {0}", msg); }
public static void CarExploded(string msg)
{ Console.WriteLine(msg); }
}
Trang 41// Remove member from the invocation lists.
public void RemoveAboutToBlow(AboutToBlow
Trang 4210.4 The Simplest Possible Delegate Example
10.5 Retrofiting the Car Type with Delegates
10.6 A more Elaborate Delegate Example
42
Trang 43Microsoft
10.6 A More Elaborate Delegate
Example
To illustrate a more advanced use of delegates, Let’s
begin by updating the Car class to include two new
Boolean member variables.
• The first is used to determine whether the automobile is due for a wash (isDirty);
• The other represents whether the car in question is in need of a tire rotation (shouldRotate)
To enable the object user to interact with this new state data,Car also defines some additional properties and an updated constructor.
Trang 44Microsoft
// Updated Car class.
public class Car
{
// Are we in need of a wash? Need to rotate tires?
private bool isDirty;
private bool shouldRotate;
// Extra params to set bools.
public Car(string name, int max, int curr,
bool washCar, bool rotateTires)
public bool Rotate
{
get{ return shouldRotate; } set{ shouldRotate = value; } }
}
Trang 45Microsoft
// Car defines yet another delegate.
public class Car
{
// Can call any method taking a Car as
// a parameter and returning nothing.
public delegate void CarMaintenanceDelegate (Car c);
}
function taking a Car as a parameter and returns nothing.
Trang 46Microsoft
Roadmap
10.7 Understanding Delegate Covarance
10.8 Greating Generic Delegates
10.9 Understanding C# Events.
10.10 The Generic C# EventHandler<T> Delegate.
10.11 Understanding C# Anonymouns Methods
10.12 Understanding Method Group Conversions
10.13 The C# 2008 Lambdas Operator.
46
Trang 47Microsoft
10.7 Understanding Delegate
Covariance
Covariance and contravariance provide a degree of
flexibility when you match method signatures with
Trang 48// Define the delegate.
{
return null;
}
Example
Trang 49public static Dogs SecondHandler()
HandlerMethod handler1 = FirstHandler;
HandlerMethod handler2 = SecondHandler; }
}//end of Progam.
Example
Trang 50 So, the assignation is valid :
// Covariance allows this delegate
HandlerMethod handler2 = SecondHandler;
Trang 51lastActivity = new System.DateTime();
this.textBox1.KeyDown += this.MultiHandler; //works with KeyEventArgs this.button1.MouseClick += this.MultiHandler; //works with
MouseEventArgs
}
// Event hander for any event with an EventArgs or
// derived class in the second parameter
private void MultiHandler(object sender, System.EventArgs e)
{
lastActivity = System.DateTime.Now;
}
Trang 52Microsoft
Roadmap
10.7 Understanding Delegate Covarance
10.8 Greating Generic Delegates
10.9 Understanding C# Events.
10.10 The Generic C# EventHandler<T> Delegate.
10.11 Understanding C# Anonymouns Methods
10.12 Understanding Method Group Conversions
10.13 The C# 2008 Lambdas Operator.
52
Trang 53Microsoft
10.8 Creating Generic Delegates
A delegate can define its own type parameters.
Code that references the generic delegate can specify the type argument to create a closed constructed type.
Just like when instantiating a generic class or calling a generic method, as shown in the following example:
public delegate void Del<T>(T item);
public static void Notify(int i) { }
Del<int> m1 = new Del<int>(Notify);
Trang 54Microsoft
10.8 Creating Generic Delegates
C# version 2.0 has a new feature called method group
conversion, it enables us to write the previous line with this simplified syntax:
Delegates defined within a generic class can use the
generic class type parameters in the same way that class methods do.
Del< int> m2 = Notify;
Trang 55Microsoft
10.8 Creating Generic Delegates
Code that references the delegate must specify the type argument of the containing class, as follows:
private static void DoWork(float[ ] items) { }
public static void TestStack()
{
Stack<float> s = new Stack<float>();
Stack<float>.StackDelegate d = DoWork;
}
Trang 56Microsoft
Generic delegates are especially useful in defining
events based on the typical design pattern.
delegate void StackEventHandler<T, U>(T sender, U eventArgs);
class Stack<T>
{
public class StackEventArgs : System.EventArgs { }
public event StackEventHandler<Stack<T>, StackEventArgs> stackEvent;
protected virtual void OnStackChanged( StackEventArgs a) {
stackEvent( this, a);
} }
Stack<double> s = new Stack<double>();
SampleClass o = new SampleClass();
s.stackEvent += o.HandleStackChange;
}
Trang 57Microsoft
Roadmap
10.7 Understanding Delegate Covarance
10.8 Greating Generic Delegates
10.9 Understanding C# Events.
10.10 The Generic C# EventHandler<T> Delegate.
10.11 Understanding C# Anonymouns Methods
10.12 Understanding Method Group Conversions
10.13 The C# 2008 Lambdas Operator.
57
Trang 59Microsoft
Events Overview
Events have the following properties:
• The publisher determines when an event is raised; the subscribers
determine what action is taken in response to the event
• An event can have multiple subscribers A subscriber can handle
multiple events from multiple publishers
• Events that have no subscribers are never called
• Events are typically used to signal user actions such as button clicks or menu selections in graphical user interfaces
• When an event has multiple subscribers, the event handlers are invoked synchronously when an event is raised
• Events can be used to synchronize threads
• In the NET Framework class library, events are based on the
EventHandler delegate and the EventArgs base class