2011-09-30 21 views
13

Nella sintassi di query posso scriverePosso accedere al "genitore" saltato di SelectMany quando si utilizza la sintassi punteggiata in Linq?

var greendoorsWithRooms = from room in house.roooms 
from door in room.doors 
where door.Color = green 
select new {d=door,r=room} 

C'è un modo ho potuto ottenere lo stesso con la sintassi punteggiata?

var greendoorsWithRooms = house.rooms.SelectMany(room=>room.Doors) 
    .Where(door=>door.Color==green) 
    .Select(door=>new{ <room is not in scope> } 

sto insegnando alcuni non-programmatori di utilizzare LINQPad contro un modello a oggetti di proprietà in modo che non abbiamo per creare GUI in giro tutti i casi dispari. Sarebbe utile se non dovessero imparare la sintassi della query. Attualmente, ho fornito snippet che risolvono ciò usando foreach, ma la domanda si presenta ancora una volta ogni tanto.

risposta

24

Questo è anche possibile (non Sintassi verificata):

house.rooms.SelectMany(room => room.Doors.Where(door => door.Color==green), 
    (room, door) => new { r=room, d=door }) 

E 'this sovraccarico SelectMany.

+0

Ecco fatto. Grazie. – Tormod

+2

Credo che sia necessario cambiare i parametri di porta e stanza sulla seconda riga in modo che il primo parametro sia la fonte e il secondo sia la raccolta. '(room, door) => new {d = door, r = room})' –

+0

Mi piacciono molto 'house.rooms.SelectMany (r => r.Doors, Tuple.Create) .Where (t => t. Item2.Color == verde) '. Potresti inserire la clausola 'where' in alcuni punti diversi, ovviamente. – Greg

2

Non è l'ideale, ma si può sempre utilizzare i tipi anonimi in SelectMany: var greendoorsWithRooms = house.rooms.SelectMany(room=> new { Room = room, Doors = room.Doors}) .Where(roomAndDoors=>roomAndDoors.Door.Color==green) .Select(roomAndDoors => ...

+0

Questo è praticamente ciò che il compilatore trasforma la sintassi della query in sotto le copertine. +1 – zinglon

7

Tutte le query LINQ vengono convertite dal compilatore in notazione puntata. La notazione fluente è solo zucchero sintattico.

Nel C# language specification, la traduzione di "da x1 a e1 da x2 a e2" è esplicitamente chiamato fuori a pagina 211.

from x1 in e1 from x2 in e2 

diventa

from * in (e1).SelectMany(x1 => e2, (x1, x2) => new { x1, x2 }) 

Dopo il libro di cucina, allora, la tua esempio sarebbe

from * in house.rooms.SelectMany(room => room.doors, (room, doors) => new { room, doors }) 

e quindi si completa la conversione in dotte d annotazione aggiungendo le clausole Where e Select. Infatti, the documentation for SelectMany fornisce la tua query come esempio!

var query = 
    petOwners 
    .SelectMany(petOwner => petOwner.Pets, 
       (petOwner, petName) => new { petOwner, petName }) 
    .Where(ownerAndPet => ownerAndPet.petName.StartsWith("S")) 
    .Select(ownerAndPet => 
      new 
      { 
       Owner = ownerAndPet.petOwner.Name, 
       Pet = ownerAndPet.petName 
      } 
    ); 

Non vi resta che cambiare "proprietario" a "camera" e "animali da compagnia" a "porte" e cambiare la vostra condizione di filtro.

Problemi correlati