Introduction
In this quick and simple article, we go over some of the extension methods defined in the System.Linq
namespace, introduced in version 3.5 of the .NET Framework.
Background
Iterating through collections and analyzing the data contained in them is a commonly performed task in programming. The LINQ extension methods are one of the tools available to .NET developers in version 3.5 to expedite and simplify working with collections.
Using the Code
We can start by assuming that somewhere in the code, a System.Collections.Generic
dictionary has been populated with data. Each key in the dictionary is a user name string
, and each value is a generic list object that holds integer values pertaining to each user:
Dictionary<string, List<int>> Users = new Dictionary<string, List<int>>();
Users.Add("Joe, Smith", new List<int>() { 20, 18, 12});
Users.Add("Jane, Doe", new List<int>() { 20, 20, 20, 18 });
Users.Add("Tom, Beck", new List<int>() { 14, 15, 20, 17 });
We may be interested in extracting all the user names from the generic dictionary into a single generic list, as follows:
List<string> lstUserNames = Users.Keys.ToList<string>();
Similarly, we can extract all the user data lists from the generic dictionary into a single generic list where each element is its own generic list:
List<List<int>> lstUserData = Users.Values.ToList<List<int>>();
We may have a requirement to sum up all the data elements that make up each user data list. For this, we can call the Aggregate
extension method, which can be applied to an object that implements IEnumerable<TSource>
and accepts a delegate
as an argument, as follows:
List<int> lstSums = new List<int>();
foreach (List<int> l in lstUserData)
{
lstSums.Add(l.Aggregate((sum, elmnt) => sum + elmnt));
}
In the above for
loop, we iterate through each element of the lstUserData
generic list, where each element happens to be its own generic list of integer values. Note the Lambda expression used to represent the delegate
passed in as an argument.
The delegate
for the Aggregate
extension method accepts two integer arguments and returns an integer value representing the sum of both input parameters. The Aggregate
extension method loops through each element of the list and performs the operation returned by the delegate
passed in.
Alternatively, and instead of using lambda expressions, we could have used anonymous methods to write an inline delegate
:
foreach (List<int> l in lstUserData)
{
lstSums.Add(l.Aggregate(delegate(int sum, int elmnt) { return sum + elmnt;} ));
}
Other extension methods can be called on the above lists. For example, we can call one for calculating the average of values in a list, checking whether a certain boolean condition is met by every element in a list and checking whether a certain condition is met by any of the elements in a list:
List<double> lstAvges = new List<double>();
List<bool> lstAllBool = new List<bool>();
List<bool> lstAnyBool = new List<bool>();
foreach (List<int> l in lstUserData)
{
lstAvges.Add(l.Average());
lstAllBool.Add(l.All(elmnt => elmnt >= 14));
lstAnyBool.Add(l.Any(elmnt => elmnt == 20));
}
The All
extension method iterates through a list and returns true
if all elements meet a specified boolean condition. In the example above, a true
is returned if all elements in the list are greater than or equal to 14
.
The Any
extension method iterates through a list and returns true
if any of the elements meet a specified boolean condition. In the example above, a true
is returned if any of the elements in the list have a value of 20
.
The above code can alternatively be written using anonymous methods when defining the input delegate
s rather than the simpler lambda expressions:
foreach (List<int> l in lstUserData)
{
lstAvges.Add(l.Average());
lstAllBool.Add(l.All(delegate(int elmnt) { return elmnt >= 14; }));
lstAnyBool.Add(l.Any(delegate(int elmnt) { return elmnt == 20; }));
}
The lstSums
generic list, in which each element is a sum of all the elements in each of the user data lists in the dictionary, can be used to call the OrderBy
extension method on it, which sorts its elements in an ascending order:
var sums = lstSums.OrderBy(elmnt => elmnt);
The resulting sorted list can then be bound to a GridView
control and displayed on a form:
GridView1.DataSource = sums;
GridView1.DataBind();
GridView1.HeaderRow.Visible = false;
Points of Interest
Lambda expressions simplify the definition of delegate
s when passed in as arguments, as shown in the code above. Additionally, the LINQ extension methods, such as the ones called in this article, offer quick and easy ways for manipulating data in collections, and returning subsets of these collections based on simply defined conditions.
History
- 16th June, 2008: Initial post