C# 3.0 LINQ has one more hidden and powerful feature; which provides you to store result of sub-expression in order to use subsequence clause. You can achieve this with the help of
let keyword. The variable created using
let is
readonly; once initialized it can’t use to store another value only good this is it can be queried.
Let’s see this with example. We have employees details in text file delimited my ‘:’, also each employee have it’s own details separated by ‘,’.
string strEmployees = "1, John, Methew:2, Nick, Althoff:3, David, Oliver:4, Sam, Peterson";
Lets write query to grab all the employee details.
string strEmployees = "1, John, Methew:2, Nick, Althoff:3, David, Oliver:4, Sam, Peterson";
//Split with :
var query = from empData in strEmployees.Split(':')
select empData;
//Split with ,
foreach (var q in query)
{
var e = q.Split(',');
Console.WriteLine("Id - {0}, First Name - {1}, Last Name - {2}",
e[0], e[1], e[2]);
}
As you can see we have to write two different logic to split one more time employee details, now let’s use
let keyword and make coding easy.
string strEmployees = "1, John, Methew:2, Nick, Althoff:3, David, Oliver:4, Sam, Peterson";
var query = from empData in strEmployees.Split(':')
let emp = empData.Split(',')
select new { Id = emp[0], FName = emp[1], LName = emp[2] };
foreach (var q in query)
{
Console.WriteLine("Id - {0}, First Name - {1}, Last Name - {2}",
q.Id, q.FName, q.LName);
}
In both query output will be same.
emp is intermediate enumerable type which we are using in next line! This is very simple example, now what compiler treats the code above? Compiler will create one sub-query that returns the anonymous type composed of the original value along with new value specified by the
let.
As its creating sub-query if you write bunch of
let statements, it will kill your performance. If its implemented in proper way
let is very good option to go with, the scenario where you need some function which operates on your select clause more then 2-3 times, you can create
let variable and use them into your select which makes your faster.
static void SummOfferNoLet()
{
var q = from c in Products
where SumOffers(c) < 10000 && SumOffers(c) > 1000
select c;
int count = q.Count();
}
static void SummOfferWithLet()
{
var q = from c in Products
let offerValue = SumOffers(c)
where offerValue < 10000 && offerValue > 100
select c;
int count = q.Count();
}
In this case
SummOfferWithLet will faster as you can see
SummOfferNoLet we need to call
SumOffers twice.
Conclusion: Using
let is powerful but if you used wrong way then it will kill the performance.