As Luke Hoban explains on his blog:
With let query clauses, you can introduce a variable into scope and use it in the subsequent query clauses. Similar to local variables in a method body, this gives you a way to avoid evaluating a common expression multiple times by storing it in a variable. This can be very useful even in much simpler queries. Of course, in the query above – let is absolutely critical.
The “query above” he refers to is a ray tracer coded as a big LINQ query full of let clauses!
Let’s see is an example from the official LINQ forum.
Someone asked how to query the following XML document:
<car name="Toyota Coupe">
<profile name="Vendor" value="Toyota"/>
<profile name="Model" value="Celica"/>
<profile name="Doors" value="2"/>
<support name="Racing" value="yes"/>
<support name="Towing" value="no"/>
</car>
<car name="Honda Accord Aerodec">
<profile name="Vendor" value="Honda"/>
<profile name="Model" value="Accord"/>
<profile name="Doors" value="4"/>
<support name="Racing" value="no"/>
<support name="Towing" value="yes"/>
</car>
</cars>
Here is one way to do it:
let profiles =
from profile in car.Elements("profile")
let supports =
from support in car.Elements("support")
select new {
select new Car {
Name = car.Attribute("name").Value,
Vendor = profiles.Single(prof => prof.Name == "Vendor").Value,
Model = profiles.Single(prof => prof.Name == "Model").Value,
Doors = int.Parse(profiles.Single(prof => prof.Name == "Doors").Value),
RacingSupport = supports.Single(sup => sup.Name == "Racing").Value == "yes"
};
It’s easier to isolate the “profile” and “support” elements in separate sequences using let clauses, as above. Then the select clause becomes simple to write.