Ответ 1
Это также возможно (не проверка синтаксиса):
house.rooms.SelectMany(room => room.Doors.Where(door => door.Color==green),
(room, door) => new { r=room, d=door })
Это this перегрузка SelectMany
.
В синтаксисе запроса я могу написать
var greendoorsWithRooms = from room in house.roooms
from door in room.doors
where door.Color = green
select new {d=door,r=room}
Есть ли способ, которым я мог бы добиться того же с точным синтаксисом?
var greendoorsWithRooms = house.rooms.SelectMany(room=>room.Doors)
.Where(door=>door.Color==green)
.Select(door=>new{ <room is not in scope> }
Я преподаю некоторым не-программистам использовать LINQPad против проприетарной объектной модели, так что нам не нужно создавать графический интерфейс вокруг каждого нечетного случая. Было бы полезно, если бы им не пришлось изучать синтаксис запроса. В настоящее время я предоставил фрагменты, разрешающие это, используя foreach, но вопрос все равно возникает время от времени.
Это также возможно (не проверка синтаксиса):
house.rooms.SelectMany(room => room.Doors.Where(door => door.Color==green),
(room, door) => new { r=room, d=door })
Это this перегрузка SelectMany
.
Все запросы LINQ преобразуются компилятором в точечную нотацию. Свободная нотация - это просто синтаксический сахар.
В спецификациях языка С# перевод "from x1 in e1 from x2 in e2" явно вызывается на стр. 211.
from x1 in e1 from x2 in e2
становится
from * in (e1).SelectMany(x1 => e2, (x1, x2) => new { x1, x2 })
Следуя кулинарной книге, ваш пример будет
from * in house.rooms.SelectMany(room => room.doors, (room, doors) => new { room, doors })
а затем вы завершите преобразование в точечную нотацию, добавив предложения Where
и Select
. Фактически документация для SelectMany
дает ваш запрос в качестве примера!
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
}
);
Вам просто нужно изменить "владельца" на "комнату" и "домашних животных" на "двери" и изменить состояние фильтра.
Не идеально, но вы всегда можете использовать анонимные типы в SelectMany
:
var greendoorsWithRooms = house.rooms.SelectMany(room=> new { Room = room, Doors = room.Doors}) .Where(roomAndDoors=>roomAndDoors.Door.Color==green) .Select(roomAndDoors => ...