That??™s all pretty wordy, but it??™s a lot simpler with examples.
Let??™s consider the event handlers we??™ve got in our little Windows Forms application.
The signatures1 of the three delegate types involved are as follows:
void EventHandler (object sender, EventArgs e)
void KeyPressEventHandler (object sender, KeyPressEventArgs e)
void MouseEventHandler (object sender, MouseEventArgs e)
Now, consider that KeyPressEventArgs and MouseEventArgs both derive from Event-
Args (as do a lot of other types??”at the time of this writing, MSDN lists 386 types that
derive directly from EventArgs). So, if you have a method that takes an EventArgs
parameter, you could always call it with a KeyPressEventArgs argument instead. It
therefore makes sense to be able to use a method with the same signature as
EventHandler to create an instance of KeyPressEventHandler??”and that??™s exactly what
C# 2 does. This is an example of contravariance of parameter types.
To see that in action, let??™s think back to listing 5.1 and suppose that we don??™t need
to know which event was firing??”we just want to write out the fact that an event has
happened. Using method group conversions and contravariance, our code becomes
quite a lot simpler, as shown in listing 5.2.
1 I??™ve removed the public delegate part for reasons of space.
142 CHAPTER 5 Fast-tracked delegates
static void LogPlainEvent(object sender, EventArgs e)
{
Console.
Pages:
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293