在Linq中使用点分子语法时,我可以访问SelectMany的跳过的“父”吗?

时间:2011-09-30 13:28:31

标签: c# linq

在查询语法中我可以写

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来对照专有对象模型,这样我们就不必围绕每个奇怪的情况创建GUI。如果他们不必学习查询语法将是有益的。目前,我已经提供了使用foreach解决此问题的片段,但问题仍然偶尔会出现。

3 个答案:

答案 0 :(得分:38)

这也是可能的:

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

SelectMany的{​​{3}}超载。

答案 1 :(得分:9)

所有LINQ查询都由编译器转换为点分表示法。流利的符号只是语法糖。

C# language specification中,在第211页明确地调出了“从e1中的x1到e2中的x2”的翻译。

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

然后您将通过添加WhereSelect子句完成转换为点分表示法。事实上,the documentation for 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
            }
    );

您只需将“所有者”更改为“房间”,将“宠物”更改为“门”并更改过滤条件。

答案 2 :(得分:2)

不理想,但您可以始终在SelectMany中使用匿名类型: var greendoorsWithRooms = house.rooms.SelectMany(room=> new { Room = room, Doors = room.Doors}) .Where(roomAndDoors=>roomAndDoors.Door.Color==green) .Select(roomAndDoors => ...