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.

250 CHAPTER 9 Lambda expressions and expression trees1 Phase 1 beg<strong>in</strong>s.2 The first parameter is of type TInput, and the first argument is of type str<strong>in</strong>g.We <strong>in</strong>fer that there must be an implicit conversion from str<strong>in</strong>g to TInput.3 The second parameter is of type Converter, and the secondargument is an implicitly typed lambda expression. No <strong>in</strong>ference is performed—wedon’t have enough <strong>in</strong>formation.4 Phase 2 beg<strong>in</strong>s.5 TInput doesn’t depend on any unfixed type parameters, so it’s fixed to str<strong>in</strong>g.6 The second argument now has a fixed <strong>in</strong>put type, but an unfixed output type. Wecan consider it to be (str<strong>in</strong>g x) => x.Length and <strong>in</strong>fer the return type as <strong>in</strong>t.Therefore an implicit conversion must take place from <strong>in</strong>t to TOutput.7 Phase 2 repeats.8 TOutput doesn’t depend on anyth<strong>in</strong>g unfixed, so it’s fixed to <strong>in</strong>t.9 There are now no unfixed type parameters, so <strong>in</strong>ference succeeds.Complicated, eh? Still, it does the job—the result is what we’d want (TInput=str<strong>in</strong>g,TOutput=<strong>in</strong>t) and everyth<strong>in</strong>g compiles without any problems. The importance ofphase 2 repeat<strong>in</strong>g is best shown with another example, however. List<strong>in</strong>g 9.15 shows twoconversions be<strong>in</strong>g performed, with the output of the first one becom<strong>in</strong>g the <strong>in</strong>put ofthe second. Until we’ve worked out the output type of the first conversion, we don’tknow the <strong>in</strong>put type of the second, so we can’t <strong>in</strong>fer its output type either.List<strong>in</strong>g 9.15Multistage type <strong>in</strong>ferencestatic void ConvertTwice(TInput <strong>in</strong>put,Converter firstConversion,Converter secondConversion){TMiddle middle = firstConversion(<strong>in</strong>put);TOutput output = secondConversion(middle);Console.WriteL<strong>in</strong>e(output);}...ConvertTwice("Another str<strong>in</strong>g",text => text.Length,length => Math.Sqrt(length));The first th<strong>in</strong>g to notice is that the method signature appears to be pretty horrific. It’snot too bad when you stop be<strong>in</strong>g scared and just look at it carefully—and certa<strong>in</strong>ly theexample usage makes it more obvious. We take a str<strong>in</strong>g, and perform a conversion onit: the same conversion as before, just a length calculation. We then take that length(an <strong>in</strong>t) and f<strong>in</strong>d its square root (a double).Phase 1 of type <strong>in</strong>ference tells the compiler that there must be a conversion fromstr<strong>in</strong>g to TInput. The first time through phase 2, TInput is fixed to str<strong>in</strong>g and we<strong>in</strong>fer that there must be a conversion from <strong>in</strong>t to TMiddle. The second time throughLicensed to Rhona Hadida

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

Saved successfully!

Ooh no, something went wrong!