1. Benefits of using LINQ - primitive types
- Filtering
- Sorting
2. Using LINQ with classes
- Filtering
- Grouping
- Grouping with math functions
- Grouping by multiple items
- Using Grouping to select a disctint set
- Distinct
3. Single, First and FirstOrDefault
4. How to write for each
5. Multiple sets manipulation
- Joining 2 sets
- Left outer join
- Combining sets
- SelectMany
6. Zip
7. Aggregate
8. OfType
9. Using let
10. Debuging LINQ query
101 examples on MSDN
Before you start using LINQ, you need to include proper namespace by: using System.Linq;
1. Benefits of using LINQ - primitive types
C#
string[] codes = new string[] { "abc", "def", "ddf" };
and you want to select a subset of the elements in the array. You can write a code like this:
C#
List<string> selection = new List<string>();
foreach (string s in codes)
{
if (s.StartsWith("d")) selection.Add(s);
}
Filtering
C#
var selection = (from s in codes where s.StartsWith("d") select s).ToList();
var selection = codes.Where(s => s.StartsWith("d")).ToList();
Sorting
C#
var selection = (from s in codes where s.StartsWith("d") orderby s[1],s[0] descending select s).ToList();
var selection = codes.Where(s => s.StartsWith("d")).OrderBy(s => s[1]).ThenByDescending(s => s[0]).ToList();
2. Using LINQ with classes
C#
//define a class that represents person
class Person
{
public string DepartmentId;
public string Name;
public int Age;
}
// populate people
List<Person< people = new List<Person>() {
new Person() { DepartmentId = "IT", Name = "John", Age=32 },
new Person() { DepartmentId = "FI", Name = "Paul", Age=43 },
new Person() { DepartmentId = "FI", Name = "George", Age=28 }
};
Filtering
C# // select whole classes from the list List<Person> itPeople = people.Where(p => p.DepartmentId == "IT").ToList(); // if you want only people names List<string> itPeopleNames = people.Where(p => p.DepartmentId == "IT").Select(p => p.Name).ToList();
Grouping
C#
var groups = from p in people group p by p.DepartmentId into g select new { MyKey = g.Key, MyGroup = g };
var groups1 = people.GroupBy(p => p.DepartmentId).Select( g => new { MyKey = g.Key, MyGroup = g });
// iterate over result
foreach (var gr in groups1)
{
string key = gr.MyKey;
foreach (var p in gr.MyGroup)
{
Person person = p;
}
}
Grouping with math functions
C#
var averages = from p in people group p by p.DepartmentId into g select new { MyKey = g.Key, AvgAge = g.Average(p => p.Age) };
var averages1 = people.GroupBy(p => p.DepartmentId).Select(g => new { MyKey = g.Key, MyAvg = g.Average(p => p.Age) });
Grouping by multiple items
C#
var averages2 = people
.GroupBy(p => new { p.DepartmentId, p.Age })
.Select(g => new { DeptId = g.Key.DepartmentId, Age = g.Key.Age, Salary = g.Average(p => p.Salary) });
Using Grouping to select a disctint set
C#
var disctincList = people
.GroupBy(p => new { p.Name, p.DepartmentId })
.Select(g => g.First());
Distinct
C# IEnumerable<Person> disctinctSet = people.Distinct(); IEnumerable<Person> disctinctSet1 = (from p in people select p).Distinct();
3. Single, First and FirstOrDefault
C# First - returns first element of sequence. Throws exception when the sequence is empty FirstOrDefault - returns first element of sequence. If the sequence is empty, returns an empty object Single - returns first element of sequence. Throws exception when the sequence is empty or has more than 1 element
4. How to write for each
C#
foreach (var p in persons)
{
p.LastName = "John";
}
it is possible to see foreach written in LINQ as below
C#
persons.Select(p => { p.LastName = "John"; return p; } ).ToList();
persons.All(p => { p.LastName = "John"; return true; } ).ToList();
5. Multiple sets manipulation
Joining 2 sets
C#
// class that presents a departement
class DepartmentO
{
public string DepartmentId;
public string Name;
}
// populate departments
List<DepartmentO> departments = new List>DepartmentO>()
{
new DepartmentO() { DepartmentId = "IT", Name = "Information Technology"},
new DepartmentO() { DepartmentId = "FI", Name = "Finance"},
};
// class that presents combined result for person and departement
class PersonWithDepartment
{
public string DepartmentId;
public string PersonName;
public string DepartmentName;
}
Now you can populate both sets and combine result with LINQ.
C#
// join two object sets - option 1
IEnumerable<PersonWithDepartment> joinedSet = from d in departments
join p in people on d.DepartmentId equals p.DepartmentId
select new PersonWithDepartment()
{
DepartmentId = p.DepartmentId,
PersonName = p.Name,
DepartmentName = d.Name
};
// join two object sets - option 2
IEnumerable<PersonWithDepartment> joinedSet2 = people.Join(
departments,
(p) => (p.DepartmentId),
(d) => (d.DepartmentId),
(p, d) => new PersonWithDepartment()
{
DepartmentId = p.DepartmentId,
PersonName = p.Name,
DepartmentName = d.Name
}
);
Left outer join
C#
var outerJoinSet = from p in people
join d in departments on p.DepartmentId equals d.DepartmentId into d1
from d2 in d1.DefaultIfEmpty()
select new
{
DepartmentId = p.DepartmentId,
PersonName = p.Name,
DepartmentName = d2.Name
};
Combining sets
C#
// create NEW set as union of two sets
List<Person> union = people.Union(
new List<Person>() {new Person() { DepartmentId = "IT", Name = "George" }}).ToList();
// add people to existing set
people.AddRange(
new List<Person>() { new Person() { DepartmentId = "IT", Name = "George" } });
// concatenate existing 2 lists - the original lists remain untouched, no new Person element gets allocated
var list1 = new List<PersonO>() { new PersonO() { DepartmentId = "IT", Name = "John" } };
var list2 = new List<PersonO>() { new PersonO() { DepartmentId = "FI", Name = "George" } };
List<PersonO> concatenated = list1.Concat(list2).ToList();
SelectMany
C#
// cross join
var list1 = new string[] { "1", "2", "3" };
var list2 = new string[] { "A", "B" };
var result1 = list1.SelectMany(l1 => list2, (l1, l2) => new { l1, l2 });
// result: {1,A}, {1,B}, {2,A}, {2,B}, {3,A}, {3,B}
// list of lists flattening
var masterList = new List>string[]>() { list1, list2 };
var result2 = masterList.SelectMany(i => i);
// result 2: 1,2,3,A,B
6. Zip
C#
string[] list1 = { "a", "b", "c" };
string[] list2 = { "X", "Y" };
var zipped = list1.Zip(list2, (i1, i2) => i1 + i2);
foreach (var item in zipped)
{
Console.WriteLine(item);
}
// Output
// aX
// bY
7. Aggregate
C#
var input = new []{1,2,3,4,5};
var result = input.Aggregate((a,b) => a * b);
// you can seed initial value
var result = input.Aggregate(10, (a,b) => a * b);
8. OfType
C#
System.Collections.ArrayList objects = new System.Collections.ArrayList(2);
objects.Add("First");
objects.Add(1);
IEnumerable<string> strings = objects.OfType<string>();
9. Using let
C#
var list = new string[] { "abc_1", "def_11", "xyz_3" };
var result =
from item in list
let number = Convert.ToInt16(item.Split('_')[1])
where number > 2
orderby number
select item;
result = list
.Select(item => new { Item = item, Code = Convert.ToInt16(item.Split('_')[1]) })
.Where(i => i.Code > 2)
.OrderBy(i => i.Code)
.Select(i => i.Item);
// result: xyz_3, def_11
10. Debuging LINQ query
C#
var numbers = new int[] { 1, 2, 3 };
var result = numbers
.Where(n => n > 2);
It can be done without rewriting to foreach loop, but some code injection is necessary.
C#
var result1 = numbers
.Select(
item =>
{
return item; // set breakpoint here - you will see 1,2,3
})
.Where(n => n > 2)
.Select(
item =>
{
return item; // set breakpoint here - you will see 3
});
// the breakpoint will be hit when code reaches ToList()
var result1debug = result1.ToList();
If you want to examine the the evaluation of the where condition
C#
var result2 = numbers
.Where( n =>
{
bool b = n > 2;
return b; // set breakpoint here
});
var result2debug = result2.ToList();