LINQ has many operators, but some get more attention than others. The most famous are the ones which can be expressed in a from clause, such as Where, OrderBy, OrderByDescending, GroupBy and Select. However, many other operators exist - here's my favorite list:
Intersect, Union, Except
These operators are the set operators intersection (AND), union (OR) and difference.
The Intersect operator returns the items that are present in both sequences as a new sequence. Here's an example:
var list1 = new List<int> { 2, 4, 9, 11, 3, 6 };
var list2 = new List<int> { 3, 8, 4, 30, 9, 16 };
var newlist = list1.Intersect(list2);
The result is 4, 9, 3 as the common elements.
Union returns all elements present in both sequences:
newlist = list1.Union(list2);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
The returned result is 2, 4, 9, 11, 3, 6, 8, 30, 16.
Except returns the difference in the sets, i.e. the elements in list1 except those that exist in list2 and list1:
newlist = list1.Except(list2);
The result is 2, 11, 6.
First, FirstOrDefault, Last, LastOrDefault
Sometimes only the first item in a resulting sequence is interesting. In this case the First() operator returns that element. However, if the sequence is empty, an exception is thrown. This may be inconvenient, and a null return value would be preferred.
This is where the FirstOrDefault() operator comes in. If the sequence is empty it returns null.
ToList, ToArray
Most LINQ operators such as Where, Union, etc. don't calculate the result of the operator right away. Instead, an object implementing IEnumerable<T> is returned which does "deferred execution". What this means is that the actual execution is done only when the sequence is enumerated. This may come as quite a surprise. Consider the previous code, with a small extra:
var list1 = new List<int> { 2, 4, 9, 11, 3, 6 };
var list2 = new List<int> { 3, 8, 4, 30, 9, 16 };
var newlist = list1.Intersect(list2);
list1.Add(30);
foreach(int x in newlist)
Console.WriteLine(x);
What would be the output? Will it include the number 30? The (possibly) surprising answer is yes! That's because the actual Intersect operator does its thing only when the foreach loop executes.
Usually this behavior is what you want, to minimize operations that may not be required right away.
Sometimes, however, you want to get a hold of the result right now, preventing further input changes to affect the result. This is exactly what the ToList() and ToArray() do. They force execution right now and return the relevant sequence immediately. Further changes to the inputs will not affect the output.
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }