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.

306 CHAPTER 11 Query expressions and LINQ to ObjectsLeft=3; Right=11Left=3; Right=12Left=3; Right=13Left=4; Right=11Left=4; Right=12Left=4; Right=13Left=4; Right=14The method the compiler calls to generate this sequence is SelectMany. It takes a s<strong>in</strong>gle<strong>in</strong>put sequence (the left sequence <strong>in</strong> our term<strong>in</strong>ology), a delegate to generateanother sequence from any element of the left sequence, and a delegate to generate aresult element given an element of each of the sequences. Here’s the signature of themethod, aga<strong>in</strong> written as if it were an <strong>in</strong>stance method on IEnumerable:public IEnumerable SelectMany (Func collectionSelector,Func resultSelector)As with the other jo<strong>in</strong>s, if the part of the query expression follow<strong>in</strong>g the jo<strong>in</strong> is a selectclause, that projection is used as the f<strong>in</strong>al argument; otherwise, a transparent identifieris <strong>in</strong>troduced to make both the left and right sequences’ range variables available.Just to make this all a bit more concrete, here’s the query expression of list<strong>in</strong>g 11.16,as the translated source code:Enumerable.Range(1, 4).SelectMany (left => Enumerable.Range(11, left),(left, right) => new {Left=left,Right=right})One <strong>in</strong>terest<strong>in</strong>g feature of SelectMany is that the execution is completely streamed—it only needs to process one element of each sequence at a time, because it uses afreshly generated right sequence for each different element of the left sequence.Compare this with <strong>in</strong>ner jo<strong>in</strong>s and group jo<strong>in</strong>s: they both load the right sequencecompletely before start<strong>in</strong>g to return any results. You should bear <strong>in</strong> m<strong>in</strong>d theexpected size of sequence, and how expensive it might be to evaluate it multipletimes, when consider<strong>in</strong>g which type of jo<strong>in</strong> to use and which sequence to use as theleft and which as the right.This behavior of flatten<strong>in</strong>g a sequence of sequences, one produced from each element<strong>in</strong> an orig<strong>in</strong>al sequence, can be very useful. Consider a situation where youmight want to process a lot of log files, a l<strong>in</strong>e at a time. We can process a seamlesssequence of l<strong>in</strong>es, with barely any work. The follow<strong>in</strong>g pseudo-code is filled <strong>in</strong> morethoroughly <strong>in</strong> the downloadable source code, but the overall mean<strong>in</strong>g and usefulnessshould be clear:var query = from file <strong>in</strong> Directory.GetFiles(logDirectory, "*.log")from l<strong>in</strong>e <strong>in</strong> new FileL<strong>in</strong>eReader(file)let entry = new LogEntry(l<strong>in</strong>e)where entry.Type == EntryType.Errorselect entry;Licensed to Rhona Hadida

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

Saved successfully!

Ooh no, something went wrong!