LINQ to Objects Code Review

Use LINQ to Objects

Code Download

  • Download Description:linq to objects download
  • .NET Framework:3.5
  • .NET Language:C#
  • Date Published:2009-07-01
  • Download Size:22 KB

Code Walkthrough

Define the Person, Role and Salary data classes to describe the data to be stored.

class Person { public Int32 ID { get; set; } public Int32 IDRole { get; set; } public String LastName { get; set; } public String FirstName { get; set; } } class Role { public Int32 ID { get; set; } public String RoleDescription { get; set; } } class Salary { public Int32 IDPerson { get; set; } public Int32 Year { get; set; } public Double SalaryYear { get; set; } }

Populate the Person, Role and Salary collections with sample data to be used. The static Main() method defines various LINQ functions to be applied against the collection data.

static List<Person> people = new List<Person> { new Person{ID = 1, IDRole = 1, LastName = "anderson", FirstName = "Brad"}, new Person{ID = 2, IDRole = 2, LastName = "gray", FirstName = "Tom"}, new Person{ID = 3, IDRole = 1, LastName = "grant", FirstName = "Mary"}, new Person{ID = 4, IDRole = 3, LastName = "cops", FirstName = "Gary"} }; static List<Role> roles = new List<Role> { new Role{ID = 1, RoleDescription = "Manager"}, new Role{ID = 2, RoleDescription = "Developer"} }; static List<Salary> salaries = new List<Salary> { new Salary{IDPerson = 1, SalaryYear = 10000, Year = 2004}, new Salary{IDPerson = 1, SalaryYear = 15000, Year = 2005} };
static void Main(string[] args) { Console.WriteLine("*** LINQ Syntax *********************************************************\n");
FilterByFirstName("Brad"); SelectAll(); FilterByIDWithRole(); SelectAllJoinWithRole(); SelectAllGroupJoinWithRole(); SelectIDRoleCountGroupBy(); SelectIDRoleCountGroupByOrderBy(); SelectAllOrderByFirstNameLastName(); SelectAllReverse(); SelectFilterByIDRoleCount(); SumSalaryJoinWithPersonID(); MinMaxSalaryJoinWithPersonID(); AverageSalaryJoinWithPersonID(); PersonEmptySequenceRange(); PersonRepeat(); PersonSalaryAll(); PersonSalaryAny(); PersonSalaryContains(); PersonToArray(); PersonToList(); PersonToLookup();
Console.WriteLine("*** Extension Methods Syntax ********************************************\n"); FilterByIndex(); SelectAllWithPosition(); FilterByIDSelectMany(); SelectAllOrderByThenBy();
Console.Read(); }

Filter the items in the People collection using first name and return the results into a implicitly typed collection. A new anonymous type is created from the properties based on the Person type.

If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them.

static void FilterByFirstName(String firstName) { var query = from p in people where p.FirstName == firstName select new { p.ID, p.IDRole, p.LastName, p.FirstName };
foreach (var atype in query) { Console.WriteLine("ID={0}, IDRole={1}, LastName={2}, FirstName={3}",atype.ID, atype.IDRole, atype.LastName, atype.FirstName); } Console.WriteLine(); }

Use the Where extension method of the IEnumerable collection class to filter items in the People collection based on index position of the item in the collection.

A Lambda expression is passed to the Where extension method as an input parameter.

static void FilterByIndex() { var query = people .Where((p, index) => p.IDRole == index);
foreach (var atype in query) { Console.WriteLine("ID={0}, IDRole={1}, LastName={2}, FirstName={3}",atype.ID, atype.IDRole, atype.LastName, atype.FirstName); } Console.WriteLine(); }

Retrieve all the items in the People collection class and return results into a Person collection.

static void SelectAll() { var query = from p in people select p;
foreach (Person person in query) { Console.WriteLine("ID={0}, IDRole={1}, LastName={2}, FirstName={3}",person.ID, person.IDRole, person.LastName, person.FirstName); } Console.WriteLine(); }

Use the Select extension method of the List collection class to retrieve items in the People collection passing in a Lambda expressions as an input parameter.

The Lambda expression passes a Person type and index value as input parameters and returns a collection of new anonymous types.

static void SelectAllWithPosition() { var query = people .Select((p, index) => new { Position = index, p.FirstName, p.LastName });
foreach (var atype in query) { Console.WriteLine("Position={0}, LastName={1}, FirstName={2}",atype.Position, atype.LastName, atype.FirstName); } Console.WriteLine(); }

Retrieve all the items in the People collection class, together with the corresponding roles in the Roles collection. Return the results into a implicitly typed collection.

See SelectAllJoinWithRole() method for alternate code example using the "join" keyword.

static void FilterByIDWithRole() { var query = from p in people where p.ID == 1 from r in roles where r.ID == p.IDRole select new { p.FirstName, p.LastName, r.RoleDescription };
foreach (var atype in query) { Console.WriteLine("FirstName={0}, LastName={1}, RoleDescription={2}",atype.FirstName, atype.LastName, atype.RoleDescription); } Console.WriteLine(); }

Use the SelectMany extension method of the IEnumerable collection class to retrieve all the items in the People collection class, together with the corresponding roles in the Roles collection.

The SelectMany extension method enumerates the People collection, uses a transform function to map each Person object to a Role object with the same ID property, and then enumerates and yields each matching Role object. Return the results into a implicitly typed collection.

static void FilterByIDSelectMany() { var query = people .Where(p => p.ID == 1) .SelectMany(p => roles .Where(r => r.ID == p.ID) .Select(r => new { p.FirstName, p.LastName, r.RoleDescription }));
foreach (var atype in query) { Console.WriteLine("FirstName={0}, LastName={1}, RoleDescription={2}",atype.FirstName, atype.LastName, atype.RoleDescription); } Console.WriteLine(); }

Retrieve all the items in the People collection class, together with the corresponding roles in the Roles collection using the "join" keyword. Return the results into a implicitly typed collection.

static void SelectAllJoinWithRole() { var query = from p in people join r in roles on p.IDRole equals r.ID select new { p.FirstName, p.LastName, r.RoleDescription };
foreach (var atype in query) { Console.WriteLine("FirstName={0}, LastName={1}, RoleDescription={2}",atype.FirstName, atype.LastName, atype.RoleDescription); } Console.WriteLine(); }

Retrieve all the items in the People collection class, together with the corresponding roles in the Roles collection using the "join" keyword. Use the DefaultIfEmpty() method to replace each empty Role item with a null value.

The DefaultIfEmpty method can be used to replace each empty element with another element. If no parameter is been provided, the empty element will be replaced with a null value.

static void SelectAllGroupJoinWithRole() { var query = from p in people join r in roles on p.IDRole equals r.ID into pr from r in pr.DefaultIfEmpty() select new { p.FirstName, p.LastName, RoleDescription = r == null ? "#No Role#" : r.RoleDescription };
foreach (var atype in query) { Console.WriteLine("FirstName={0}, LastName={1}, RoleDescription={2}",atype.FirstName, atype.LastName, atype.RoleDescription); } Console.WriteLine(); }

Retrieve number of unique roles based on the items stored in the People collection class. Use the "group by" keyword and return a implicitly typed collection using the Count() method to count the number of unique roles. Results are returned in no specific order.

static void SelectIDRoleCountGroupBy() { var query = from p in people group p by p.IDRole into pg select new { pg.Key, IDRoleCount = pg.Count() };
foreach (var atype in query) { Console.WriteLine("IDRole={0}, Count={1}",atype.Key, atype.IDRoleCount); } Console.WriteLine(); }

Retrieve number of unique roles based on the items stored in the People collection class. Use the "group by" keyword to group like items and the "oorderby" keyword to order results by role ID. Return a implicitly typed collection using the Count() method to count the number of unique roles.

static void SelectIDRoleCountGroupByOrderBy() { var query = from p in people group p by p.IDRole into pg orderby pg.Key descending select new { pg.Key, IDRoleCount = pg.Count() };
foreach (var atype in query) { Console.WriteLine("IDRole={0}, Count={1}",atype.Key, atype.IDRoleCount); } Console.WriteLine(); }

Retrieve all the items in the People collection class ordered by first name and last name properties, and return results into a Person collection. Use the "orderby" keyword to order results as required.

static void SelectAllOrderByFirstNameLastName() { var query = from p in people orderby p.FirstName, p.LastName select p;
foreach (Person person in query) { Console.WriteLine("ID={0}, IDRole={1}, LastName={2}, FirstName={3}",person.ID, person.IDRole, person.LastName, person.FirstName); } Console.WriteLine(); }

Use the OrderBy and the ThenBy extension methods of the IEnumerable collection class to retrieve all the items in the People collection class, ordered by first name and last name properties. Return results into a implicitly typed collection.

static void SelectAllOrderByThenBy() { var query = people.OrderBy(p => p.FirstName) .ThenBy(p => p.LastName);
foreach (var atype in query) { Console.WriteLine("ID={0}, IDRole={1}, LastName={2}, FirstName={3}",atype.ID, atype.IDRole, atype.LastName, atype.FirstName); } Console.WriteLine(); }

Use the Reverse extension method of the IEnumerable collection class to retrieve all the items in the People collection class in reverse order. Return results into a Person collection.

static void SelectAllReverse() { var query = ( from p in people select p ) .Reverse();
foreach (Person person in query) { Console.WriteLine("ID={0}, IDRole={1}, LastName={2}, FirstName={3}",person.ID, person.IDRole, person.LastName, person.FirstName); } Console.WriteLine(); }

Use the Count extension method of the IEnumerable collection class to retrieve the number of items in the People collection class with role ID of 1. Return integer result.

static void SelectFilterByIDRoleCount() { Int32 numCount = ( from p in people where p.IDRole == 1 select p ) .Count();
Console.WriteLine("IDRole=1, Count={0}", numCount.ToString()); Console.WriteLine(); }

Retrieve all the items in the People collection class, together with the corresponding yearly salary in the Salaries collection using the "join" keyword. Return the results into a implicitly typed collection.

Use the "group by" keyword to group results in the implicitly typed collection by lastname property. Return result into a implicitly typed collection.

Use the Sum extension method of the IEnumerable collection class to calculate the total salary per person.

static void SumSalaryJoinWithPersonID() { var query = from p in people join s in salaries on p.ID equals s.IDPerson select new { p.FirstName, p.LastName, s.SalaryYear }; var querySum = from q in query group q by q.LastName into gp select new { LastName = gp.Key, TotalSalary = gp.Sum(q => q.SalaryYear) };
foreach (var atype in querySum) { Console.WriteLine("LastName={0}, TotalSalary={1}",atype.LastName, atype.TotalSalary); } Console.WriteLine(); }

Retrieve all the items in the Person collection class, together with the corresponding salaries in the Salaries collection using the "join" keyword. Return all the salaries into a implicitly typed collection.

Display the minimum and maximum salary based on data in the implicity typed collection.

static void MinMaxSalaryJoinWithPersonID() { var query = from p in people join s in salaries on p.ID equals s.IDPerson select s.SalaryYear;
Console.WriteLine("Minimum Salary={0}, Maximum Salary={1}",query.Min(), query.Max()); Console.WriteLine(); }

Retrieve all the items in the Person collection class, together with the corresponding salaries in the Salaries collection using the "join" keyword. Return all the salaries into a implicitly typed collection.

Display the average salary based on data in the the implicity typed collection.

static void AverageSalaryJoinWithPersonID() { var query = from p in people join s in salaries on p.ID equals s.IDPerson select s.SalaryYear;
Console.WriteLine("Average Salary={0}", query.Average()); Console.WriteLine(); }

Create an empty Enumerable collection of type Person. Use the "Range" keyword to generate a sequence of numbers in between the specified range, and put these values into the Enumerable collection.

static void PersonEmptySequenceRange() { IEnumerable<Person> p = Enumerable.Empty<Person>(); Console.WriteLine("Empty Person: {0}", p.ToString()); ObjectDumper.Write(p);
var query = Enumerable.Range(1,10);
foreach (var atype in query) { Console.WriteLine("Range={0}", atype.ToString()); } Console.WriteLine(); }

Create an Enumerable collection of type Person. Use the "Repeat" keyword to generate a sequence of one particular Person object repeated 10 times, and put these values into the Enumerable Person collection.

static void PersonRepeat() { IEnumerable<Person> person = Enumerable.Repeat(people[0], 10);
foreach (Person p in person) { Console.WriteLine("ID={0}, IDRole={1}, LastName={2}, FirstName={3}",p.ID, p.IDRole, p.LastName, p.FirstName); } Console.WriteLine(); }

Retrieve all the items in the Salaries collection, creating a numeric collection of salary values.

Use the All extension method to return all salary values greater than a certain amount.

static void PersonSalaryAll() { var query = from s in salaries select s.SalaryYear;
Console.WriteLine("Are all salaries > 15000? {0}",query.All(s => s > 15000) ? "Yes" : "No");
Console.WriteLine("Are all salaries > 5000? {0}",query.All(s => s > 5000) ? "Yes" : "No");
Console.WriteLine(); }

Retrieve all the items in the Salaries collection, creating a numeric collection of salary values.

Use the Any extension method to return all salary values matching a certain criteria.

static void PersonSalaryAny() { var query = from s in salaries select s.SalaryYear;
Console.WriteLine("Are any salaries > 15000? {0}",query.Any(s => s > 15000) ? "Yes" : "No");
Console.WriteLine("Are any salaries == 10000? {0}",query.Any(s => s == 10000) ? "Yes" : "No");
Console.WriteLine(); }

Retrieve all the items in the Salaries collection, creating a numeric collection of salary values.

Use the Contains extension method to return all salary values matching a certain criteria.

static void PersonSalaryContains() { var query = from s in salaries select s.SalaryYear;
Console.WriteLine("Does sequence have a salary == 15000? {0}",query.Contains(15000) ? "Yes" : "No");
Console.WriteLine("Does sequence have a salary == 12000? {0}",query.Contains(12000) ? "Yes" : "No");
Console.WriteLine(); }

Retrieve all the items in the Person collection that have a last name containing four letters. Return results into a String collection.

Use the ToArray extension method to create an array of string values from the result String collection.

static void PersonToArray() { var query = from p in people where p.LastName.Length == 4 select p.LastName;
String[] names = query.ToArray();
for (int i = 0; i < names.Length; i++) { Console.WriteLine("Last name: {0}", names[i]); } Console.WriteLine(); }

Retrieve all the items in the Person collection that have a last name containing four letters. Return results into a String collection.

Use the ToList extension method to create a generic list of string values from the result String collection.

static void PersonToList() { var query = from p in people where p.LastName.Length == 4 select p.LastName;
List<String> names = query.ToList<String>();
foreach(String name in names) { Console.WriteLine("Last name: {0}", name); } Console.WriteLine(); }

Retrieve all the items in the Person collection class, together with the corresponding salaries in the Salaries collection where the Person ID has a value of 1. Return all the salaries into a enumerable collection of type Salary.

Use the ToLookup extension method, which returns an object of type ILookup, to retrieve the year and salary values from the collection.

static void PersonToLookup() { IEnumerable<Salary> q = from p in people where p.ID == 1 from s in salaries where s.IDPerson == p.ID select s;
ILookup<String, Salary> d = q.ToLookup(k => k.Year.ToString(), k => k);
foreach (var itm in d) { foreach (Salary salary in itm) Console.WriteLine("Year {0} - Salary: {1}", itm.Key, salary.SalaryYear.ToString()); } Console.WriteLine(); }