Saturday, December 25, 2010

Let.It.Be

Just another stupid question, bad for checking knowledge, but good enough to find out one's "tactical" architecture design capabilities.

It's not a secret that C# translates LINQ queries into chain of extension method calls. For instance, the following code snippet:

var entities = from e in list
               where e.Id > 10
               select e.Name;

will be transcribed as

var entities = list.Where(e=>e.Id > 10).Select(e=>e.Name);

But how is 'let' keyword transcribed? There is no .Let() method in LINQ. Could you suggest your solution?



To solve this tiny puzzle, let's point all requirements for 'let' keyword.
  1. Variables defined in 'let' sections are read-only and could not be reinitialized (according to LINQ documentation).
  2. 'let' should not be just an alias - a variable defined in 'let' should not be recalclated every time.
  3. Variable defined in 'let' should has the same scope as 'from' variable.
Let's also write down an example of 'let' usage:

var entities = from e in list
               let length = e.Name.Length
               where e.Id > 10
               select new {e.Id, length}

We need some mechanism to map an 'e' variable to the set of two variables - 'e' and 'length', or, in LINQ words, we need map each element from 'list' to an object with two properties - 'e' equals to an element and 'length' equals to 'element.Name.Length' - the obvious choice is anonymous type.

So let's try to write this down:


var entities = list.Select(x=> new{e=x, length=x.Name.Length).Where(x=>x.e.Id > 10).Select(x=>new {x.e.Id, x.length});

As you can see, this solution satisfies all our conditions. And, in fact, LINQ uses exactly the same mechanism.

No comments:

Post a Comment