C H A P T E R 10
Delegates, Events, and Lambda
Expressions
Up to this point in the text, most of the applications you developed added various bits of code to Main(),
which, in some way or another, sent requests to a given object. However, many applications require that
an object be able to communicate back to the entity that created it using a callback mechanism. While
callback mechanisms can be used in any application, they are especially critical for graphical user
interfaces in that controls (such as a button) need to invoke external methods under the correct
circumstances (when the button is clicked, when the mouse enters the button surface, and so forth).
Under the .NET platform, the delegate type is the preferred means of defining and responding to
callbacks within applications. Essentially, the .NET delegate type is a type-safe object that “points to” a
method or a list of methods that can be invoked at a later time. Unlike a traditional C++ function pointer,
however, .NET delegates are classes that have built-in support for multicasting and asynchronous
method invocation.
In this chapter, you will learn how to create and manipulate delegate types, then you’ll investigate
the C# event keyword, which streamlines the process of working with delegate types. Along the way, you
will also examine several delegate- and event-centric language features of C#, including anonymous
methods and method group conversions.
I wrap up this chapter by examining lambda expressions. Using the C# lambda operator (=>), you
can specify a block of code statements (and the parameters to pass to those code statements) wherever a
strongly typed delegate is required. As you will see, a lambda expression is little more than an
anonymous method in disguise, and provides a simplified approach to working with delegates.
Understanding the .NET Delegate Type
Before formally defining .NET delegates, let’s gain a bit of perspective. Historically, the Windows API
made frequent use of C-style function pointers to create entities termed callback functions, or simply
callbacks. Using callbacks, programmers were able to configure one function to report back to (call back)
another function in the application. With this approach, Windows developers were able to handle
button-clicking, mouse-moving, menu-selecting, and general bidirectional communications between
two entities in memory.
The problem with standard C-style callback functions is that they represent little more than a raw
address in memory. Ideally, you should be able to configure callbacks to include additional type-safe
information such as the number of (and types of) parameters and the return type (if any) of the method
pointed to. Sadly, this is not the case in traditional callback functions and, as you might suspect, they
can therefore be a frequent source of bugs, hard crashes, and other runtime disasters. Nevertheless,
callbacks are useful entities.
359