2011-09-30 8 views
13

En la sintaxis de consulta Puedo escribir¿Puedo acceder al "padre" omitido de SelectMany cuando uso sintaxis punteada en Linq?

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

¿Hay alguna manera de que pudiera lograr el mismo con la sintaxis de puntos?

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

enseño algunos no programadores utilizar LINQPad contra un modelo de objetos de propiedad de manera que no tenemos para crear GUI alrededor de cada caso extraño. Sería beneficioso si no tuvieran que aprender la sintaxis de la consulta. En este momento, he proporcionado fragmentos que resuelven esto utilizando foreach, pero la pregunta aún aparece de vez en cuando.

Respuesta

24

Esto también es posible (no comprobado la sintaxis):

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

Se this es la sobrecarga de SelectMany.

+0

Eso es todo. Gracias. – Tormod

+2

Creo que necesita cambiar los parámetros de puerta y habitación en segunda línea para que el primer parámetro sea la fuente y el segundo sea la colección. '(habitación, puerta) => nuevo {d = puerta, r = habitación})' –

+0

Me gusta mucho 'house.rooms.SelectMany (r => r.Doors, Tuple.Create) .Where (t => t. Item2.Color == verde) '. Podrías poner la cláusula 'where' en algunos lugares diferentes, por supuesto. – Greg

2

No es ideal, pero siempre se puede utilizar los tipos anónimos en SelectMany: var greendoorsWithRooms = house.rooms.SelectMany(room=> new { Room = room, Doors = room.Doors}) .Where(roomAndDoors=>roomAndDoors.Door.Color==green) .Select(roomAndDoors => ...

+0

Esto es más o menos lo que el compilador convierte la sintaxis de la consulta en las cubiertas. +1 – zinglon

7

Todas las consultas LINQ son convertidas por el compilador en notación punteada. La notación fluida es solo azúcar sintáctica.

En el C# language specification, la traducción de "de x1 en e1 de x2 en e2" se llama explícitamente en la página 211.

from x1 in e1 from x2 in e2 

convierte

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

Siguiendo el libro de cocina a continuación, su ejemplo sería

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

y luego completaría la conversión a dotte d notación añadiendo Where y Select cláusulas. De hecho, the documentation for SelectMany da su consulta como un ejemplo!

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 
      } 
    ); 

sólo hay que cambiar "propietario" a "sala" y "mascotas" a "puertas" y cambiar su condición de filtro.

Cuestiones relacionadas