CHAPTER 10 DELEGATES, EVENTS, AND LAMBDA EXPRESSIONS
Understanding C# Events
Delegates are fairly interesting constructs in that they enable objects in memory to engage in a two-way
conversation. However, working with delegates in the raw can entail the creation of some boilerplate
code (defining the delegate, declaring necessary member variables, and creating custom registration and
unregistration methods to preserve encapsulation, etc.).
Moreover, when you use delegates in the raw as your application’s callback mechanism, if you do
not define a class’s delegate member variables as private, the caller will have direct access to the delegate
objects. In this case, the caller could reassign the variable to a new delegate object (effectively deleting
the current list of functions to call) and, worse yet, the caller would be able to directly invoke the
delegate’s invocation list. To illustrate this problem, consider the following reworking (and
simplification) of the Car class from the previous CarDelegate example:
public class Car
{
public delegate void CarEngineHandler(string msgForCaller);
// Now a public member!
public CarEngineHandler listOfHandlers;
}
// Just fire out the Exploded notification.
public void Accelerate(int delta)
{
if (listOfHandlers != null)
listOfHandlers("Sorry, this car is dead...");
}
Notice that we no longer have private delegate member variables encapsulated with custom
registration methods. Because these members are indeed public, the caller can directly access the
listOfHandlers member variable and reassign this type to new CarEngineHandler objects and invoke the
delegate whenever it so chooses:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Agh! No Encapsulation! *****\n");
// Make a Car.
Car myCar = new Car();
// We have direct access to the delegate!
myCar.listOfHandlers = new Car.CarEngineHandler(CallWhenExploded);
myCar.Accelerate(10);
// We can now assign to a whole new object...
// confusing at best.
myCar.listOfHandlers = new Car.CarEngineHandler(CallHereToo);
myCar.Accelerate(10);
// The caller can also directly invoke the delegate!
myCar.listOfHandlers.Invoke("hee, hee, hee...");
Console.ReadLine();
378