Linq and Lambda are two important tools for any .Net developer. Anyone who says otherwise simply does not understand them. Not only do they create less code and a readable approach to sets and flow control, but they enable many compile-time validations that were otherwise either impossible or so complex, most of us tended to skipped them. However, Linq is not Lambda.
Linq: there are two syntaxes.
The first is Query syntax:
var _Results = from record in _List
where record.Value == 1
orderby record.Name
select record;
Some people like the above syntax because it reminds them of TSQL. Some people like it because you can literally read it aloud and it tends to be understandable. But some people prefer the second syntax.
The second is Method syntax:
var _Results = _List
.Where(x => x.Value == 1)
.OrderBy(x => x.Name);
.Select(x => x);
In Method syntax we see Lambda for the first time. You cannot have Lambda without the Lambda symbol of “=>”. People pronounce it as “becomes”, “goes to”, “is of”, and “such that”. I just say “Lambda”, but that’s probably because I don’t want to get swatted in the how-do-you-say-it Jihad.
Note: The “Select(x => x)“ in the Method Syntax is unnecessary; I included it to illustrate the symmetry of the two techniques; they are semantically identical. They result in identical MSIL. They have identical runtime execution. Choosing one over the other is purely preference-based.
Lambda: Shorthand and Longhand
Handy Lambda shorthand syntax like “(x => x.Value == 1)” creates a quick predicate. In this simple sample, we have quite a view pieces. More than you might think:
1. We have the Parameter – which is the “x” we use to indicate the item’s instance.
2. We have the Property – which is the “Value” property of the item we will test.
3. We have the Constant – which is the number 1 used in our test.
4. We have the Operator (or Body) – which is the “==” that compares the Property and Constant.
After a little use, shorthand Lambda is easy to read. The syntax is shorthand for the Lambda Expression Tree. The Expression Tree represents the Lambda expression’s components piece-by-piece.
Building Lambda Expression Trees the long way
Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y. You can compile and run code represented by expression trees. This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. http://msdn.microsoft.com/en-us/library/bb397951.aspx
// sample dto
public class Item
{
public int Value { get; set; }
public string Name { get; set; }
}
static void Main(string[] args)
{
var _List = new List<Item>
{
new Item{ Name = "Smith", Value = 3},
new Item{ Name = "Smith", Value = 2},
new Item{ Name = "Wesson", Value = 1},
new Item{ Name = "Wesson", Value = 4},
}.AsQueryable<Item>();
var _Type = typeof(Item);
#region Where
var _WhereProperty = _Type.GetProperty("Value");
var _WhereParameter = Expression.Parameter(typeof(Item), "x");
// (x.Value == 1)
var _WhereLeft1 = Expression.PropertyOrField
(_WhereParameter, _WhereProperty.Name);
var _WhereRight1 = Expression.Constant(1, typeof(int));
var _WhereBody1 = Expression.Equal(_WhereLeft1, _WhereRight1);
// (x.Value != 4)
var _WhereLeft2 = Expression.PropertyOrField
(_WhereParameter, _WhereProperty.Name);
var _WhereRight2 = Expression.Constant(4, typeof(int));
var _WhereBody2 = Expression.NotEqual(_WhereLeft2, _WhereRight2);
// (x.Value == 1 || (x.Value != 4))
var _WhereBody = Expression.OrElse(_WhereBody1, _WhereBody2);
var _WhereLambda = Expression.Lambda<Func<Item, bool>>
(_WhereBody, _WhereParameter);
// apply the Where
_List = _List.Where(_WhereLambda);
#endregion
#region OrderBy
var _OrderByProperty = _Type.GetProperty("Value");
var _OrderByParameter = Expression.Parameter(typeof(Item), "x");
// OrderBy(x => x.Value)
var _OrderByBody = Expression.Property
(_OrderByParameter, _OrderByProperty.Name);
// allow the return type to be object instead of Int16
var _OrderByConverted = Expression.Convert(_OrderByBody, typeof(object));
var _OrderByLambda = Expression.Lambda<Func<Item, object>>
(_OrderByConverted, _OrderByParameter);
// apply the OrderBy
_List = _List.OrderBy(_OrderByLambda);
#endregion
// display
_List.ToList<Item>().ForEach(x => Console.WriteLine(x.Value));
// wait
Console.Read();
}
The resulting tree would be presented in shorthand like this:
var _Results = from record in _List
where record.Value == 1 || record.Value != 4
orderby record.Value
select record;
or
var _Results = _List
.Where(x => x.Value == 1 || x.Value != 4)
.OrderBy(x => x.Value);
.Select(x => x);
Conclusion
In either case, the longhand Expression Tree gives two things to us: 1) it gives us an under-the-hood view to help us understand the components of an expression. And, 2) it gives us a method by which we can create dynamic Lambda expressions.
PS: Here’s how to perform a GroupBy dynamically: http://stackoverflow.com/questions/7114922/linq-writing-an-extension-method-to-get-the-row-with-maximum-value-for-each-gro/7115421#7115421
0 comments:
Post a Comment