开发者

Can I access the skipped "parent" of SelectMany when using dotted syntax in Linq?

In query syntax I can write

var greendoorsWithRooms = from room in house.roooms
from door in room.doors
where door.Color = green
select new {d=开发者_高级运维door,r=room}

Is there a way I could achieve the same with dotted syntax?

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

I am teaching some non-programmers to use LINQPad against a proprietary object model so that we don't have to create GUI around every odd case. It would be beneficial if they didn't have to learn query syntax. Presently, I've supplied snippets solving this using foreach, but the question still comes up once in a while.


This is also possible:

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

It's this overload of SelectMany.


All LINQ queries are converted by the compiler into method (dotted) syntax. Query notation is just syntactic sugar.

In the C# language specification, the translation of "from x1 in e1 from x2 in e2" is explicitly called out on page 211.

from x1 in e1 from x2 in e2

becomes

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

Following the cookbook then, your example would be

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

and then you would complete the conversion to dotted notation by adding Where and Select clauses. In fact the documentation for SelectMany gives your query as an example!

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

You just have to change "owner" to "room" and "pets" to "doors" and change your filter condition.


Not ideal, but you could always use anonymous types in SelectMany: var greendoorsWithRooms = house.rooms.SelectMany(room=> new { Room = room, Doors = room.Doors}) .Where(roomAndDoors=>roomAndDoors.Door.Color==green) .Select(roomAndDoors => ...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜