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.

142 CHAPTER 5 Fast-tracked delegatesList<strong>in</strong>g 5.2Demonstration of method group conversions and delegate contravariancestatic void LogPla<strong>in</strong>Event(object sender, EventArgs e){Console.WriteL<strong>in</strong>e ("An event occurred");}...Button button = new Button();button.Text = "Click me";button.Click += LogPla<strong>in</strong>Event;button.KeyPress += LogPla<strong>in</strong>Event;button.MouseClick += LogPla<strong>in</strong>Event;Form form = new Form();form.AutoSize=true;form.Controls.Add(button);Application.Run(form);We’ve managed to completely remove the two handler methods that dealt specificallywith key and mouse events, us<strong>in</strong>g one event handl<strong>in</strong>g method B for everyth<strong>in</strong>g. Ofcourse, this isn’t terribly useful if you want to do different th<strong>in</strong>gs for different types ofevents, but sometimes all you need to know is that an event occurred and, potentially,the source of the event. The subscription to the Click event C only uses the implicitconversion we discussed <strong>in</strong> the previous section because it has a simple EventArgsparameter, but the other event subscriptions D <strong>in</strong>volve the conversion and contravariancedue to their different parameter types.I mentioned earlier that the .NET 1.0/1.1 event handler convention didn’t makemuch sense when it was first <strong>in</strong>troduced. This example shows exactly why the guidel<strong>in</strong>esare more useful with <strong>C#</strong> 2. The convention dictates that event handlers shouldhave a signature with two parameters, the first of which is of type object and is theorig<strong>in</strong> of the event, and the second of which carries any extra <strong>in</strong>formation about theevent <strong>in</strong> a type deriv<strong>in</strong>g from EventArgs. Before contravariance became available,this wasn’t useful—there was no benefit to mak<strong>in</strong>g the <strong>in</strong>formational parameterderive from EventArgs, and sometimes there wasn’t much use for the orig<strong>in</strong> of theevent. It was often more sensible just to pass the relevant <strong>in</strong>formation directly <strong>in</strong> theform of normal parameters, just like any other method. Now, however, you can use amethod with the EventHandler signature as the action for any delegate type thathonors the convention.Demonstrat<strong>in</strong>g covariance of return types is a little harder as relatively few built-<strong>in</strong>delegates are declared with a nonvoid return type. There are some available, but it’s easierto declare our own delegate type that uses Stream as its return type. For simplicitywe’ll make it parameterless: 2delegate Stream StreamFactory();Uses methodgroup conversionB Handlesall eventsWe can now use this with a method that is declared to return a specific type of stream,as shown <strong>in</strong> list<strong>in</strong>g 5.3. We declare a method that always returns a MemoryStream with2Return type covariance and parameter type contravariance can be used at the same time, although you’reunlikely to come across situations where it would be useful.CUses conversionD and contravarianceLicensed to Rhona Hadida

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

Saved successfully!

Ooh no, something went wrong!