13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Covariance and contravariance141method group conversion to convert to the pla<strong>in</strong> System.Delegate type s<strong>in</strong>ce thecompiler doesn’t know which specific delegate type to create an <strong>in</strong>stance of. This is abit of a pa<strong>in</strong>, but you can still be slightly briefer than <strong>in</strong> <strong>C#</strong> 1 by mak<strong>in</strong>g the conversionexplicit. For example:Delegate <strong>in</strong>valid = SomeMethod;Delegate valid = (ThreadStart)SomeMethod;As with generics, the precise rules of conversion are slightly complicated, and the “justtry it” rule works very well: if the compiler compla<strong>in</strong>s that it doesn’t have enough<strong>in</strong>formation, just tell it what conversion to use and all should be well. If it doesn’t compla<strong>in</strong>,you should be f<strong>in</strong>e. For the exact details, consult the language specification.Speak<strong>in</strong>g of possible conversions, there may be more than you expect, as we’ll see <strong>in</strong>our next section.5.3 Covariance and contravarianceWe’ve already talked quite a lot about the concepts of covariance and contravariance<strong>in</strong> different contexts, usually bemoan<strong>in</strong>g their absence, but delegate constructionis the one area <strong>in</strong> which they are actually available <strong>in</strong> <strong>C#</strong>. If you want to refreshyourself about the mean<strong>in</strong>g of the terms at a relatively detailed level, refer back tosection 2.3.2—but the gist of the topic with respect to delegates is that if it would bevalid (<strong>in</strong> a static typ<strong>in</strong>g sense) to call a method and use its return value everywherethat you could <strong>in</strong>voke an <strong>in</strong>stance of a particular delegate type and use its returnvalue, then that method can be used to create an <strong>in</strong>stance of that delegate type.That’s all pretty wordy, but it’s a lot simpler with examples.Let’s consider the event handlers we’ve got <strong>in</strong> our little W<strong>in</strong>dows Forms application.The signatures 1 of the three delegate types <strong>in</strong>volved 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 writ<strong>in</strong>g, MSDN lists 386 types thatderive directly from EventArgs). So, if you have a method that takes an EventArgsparameter, you could always call it with a KeyPressEventArgs argument <strong>in</strong>stead. Ittherefore makes sense to be able to use a method with the same signature asEventHandler to create an <strong>in</strong>stance of KeyPressEventHandler—and that’s exactly what<strong>C#</strong> 2 does. This is an example of contravariance of parameter types.To see that <strong>in</strong> action, let’s th<strong>in</strong>k back to list<strong>in</strong>g 5.1 and suppose that we don’t needto know which event was fir<strong>in</strong>g—we just want to write out the fact that an event hashappened. Us<strong>in</strong>g method group conversions and contravariance, our code becomesquite a lot simpler, as shown <strong>in</strong> list<strong>in</strong>g 5.2.1I’ve removed the public delegate part for reasons of space.Licensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!