Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

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.

like image 264
Tormod Avatar asked Sep 30 '11 13:09

Tormod


2 Answers

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.

like image 197
4 revs, 2 users 92% Avatar answered Nov 17 '22 03:11

4 revs, 2 users 92%


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.

like image 15
Raymond Chen Avatar answered Nov 17 '22 02:11

Raymond Chen