为什么要使用LINQ
一、为什么要使用LINQ
要理解为什么使用LINQ,先来看下面一个例子。假设有一个整数类型的数组,找到里面的偶数并进行降序排序。
在C#2.0以前,如果要实现这样的功能,我们必须使用’foreach’或’for’循环来遍历数组,先找到偶数然后在降序排序,相关代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqOfSelectOperation
{
class Program
{
static void Main(string[] args)
{
// 查询出数组中的偶数并排序
int[] ints = { 5, 2, 0, 66, 4, 32, 7, 1 };
// 定义一个整数类型的集合,用来存放数组中的偶数
List<int> list = new List<int>();
// 遍历数组查询出偶数放到集合中
foreach (int i in ints)
{
// 如果是偶数,把偶数加入到集合中
if (i % 2 == 0)
{
list.Add(i);
}
}
// 正序排序
list.Sort();
// 反转
list.Reverse();
// 输出
Console.WriteLine(string.Join(",",list));
Console.ReadKey();
}
}
}
用for循环很麻烦,而且不可维护和可读。C#2.0引入了delegate,可以使用委托来处理这种场景,代码如下图所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqOfSelectOperation
{
// 定义委托
delegate bool FindEven(int item);
class IntExtension
{
public static int[] where(int[] array, FindEven dele)
{
int[] result=new int[5];
int i = 0;
foreach (int item in array)
{
if (dele(item))
{
result[i]=item;
i++;
}
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
// 查询出数组中的偶数并排序
int[] ints = { 5, 2, 0, 66, 4, 32, 7, 1 };
//delegate(int item){return item % 2 == 0;}表示委托的实现
List<int> list = IntExtension.where(ints, delegate(int item)
{
return item % 2 == 0;
}).ToList();
// 正序排序
list.Sort();
// 反转
list.Reverse();
// 输出
Console.WriteLine(string.Join(",", list));
Console.ReadKey();
}
}
}
所以,有了C#2.0,通过使用委托有了代理的优势,不必使用for循环来查询不同条件的数组。例如你可以使用相同的委托来查找数组中的奇数,并降序排序输出,代码如下图所示:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqOfSelectOperation
{
// 定义委托
delegate bool FindEven(int item);
class IntExtension
{
public static int[] where(int[] array, FindEven dele)
{
int[] result=new int[3];
int i = 0;
foreach (int item in array)
{
if (dele(item))
{
result[i]=item;
i++;
}
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
// 查询出数组中的奇数并排序
int[] ints = { 5, 2, 0, 66, 4, 32, 7, 1 };
//delegate(int item){return item % 2 != 0;}表示委托的实现
List<int> list = IntExtension.where(ints, delegate(int item)
{
return item % 2 != 0;
}).ToList();
// 正序排序
list.Sort();
// 反转
list.Reverse();
// 输出
Console.WriteLine(string.Join(",", list));
Console.ReadKey();
}
}
}
虽然使用delegate可以使程序的可读性增加了,但是C#团队认为他们仍然需要使代码更加紧凑和可读,所以他们在C#3.0中引入了扩展方法、Lambda表达式、匿名类型等新特性,你可以使用C#3.0的这些新特性,这些新特性的使用LINQ的前提,可以用来查询不同类型的集合,并返回需要的结果。
下面的示例演示了如何使用LINQ和Lambda表达式根据特定条件来查询数组,示例代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqOfSelectOperation
{
class Program
{
static void Main(string[] args)
{
// 查询出数组中的奇数并排序
int[] ints = { 5, 2, 0, 66, 4, 32, 7, 1 };
// 使用LINQ和Lambda表达式查询数组中的偶数
int[] intEvens= ints.Where(p => p % 2 == 0).ToArray();
// 使用LINQ和Lambda表达式查询数组中的奇数
int[] intOdds = ints.Where(p => p % 2 != 0).ToArray();
// 输出
Console.WriteLine("偶数:" + string.Join(",", intEvens));
Console.WriteLine("奇数:" + string.Join(",", intOdds));
Console.ReadKey();
}
}
}
在上面的例子中可以看到,我们在单个语句中使用LINQ和Lambda表达式指定不同的查询条件,因此,LINQ使代码更加紧凑和可读,并且它也可以用于查询不同的数据源。看到这里的时候,你可能会问:究竟什么是LINQ呢?下面将会具体讲解什么是LINQ。
二、什么是LINQ
数据的定义和操作
LINQ 语言级集成查询 API 的意图提供一套统一且对称的方式,让程序员在广义的数据上得到和操作“数据“。
用C# 语言创建 查询表达式 Query Expression 的实体
Linq 表达式是强类型的
长期以来,开发社区形成以下的格局:
- 1、面向对象与数据访问两个领域长期分裂,各自为政。
- 2、编程语言中的数据类型与数据库中的数据类型形成两套不同的体系,例如:
C#中字符串用string数据类型表示。
SQL中字符串用NVarchar/Varchar/Char数据类型表示。
- 3、SQL编码体验落后
没有智能感知效果。
没有严格意义上的强类型和类型检查。
- 4、SQL和XML都有各自的查询语言,而对象没有自己的查询语言。
上面描述的问题,都可以使用LINQ解决,那么究竟什么是LINQ呢?
LINQ(Language Integrated Query)即语言集成查询。
LINQ是一组语言特性和API,使得你可以使用统一的方式编写各种查询。用于保存和检索来自不同数据源的数据,从而消除了编程语言和数据库之间的不匹配,以及为不同类型的数据源提供单个查询接口。
LINQ总是使用对象,因此你可以使用相同的查询语法来查询和转换XML、对象集合、SQL数据库、ADO.NET数据集以及任何其他可用的LINQ提供程序格式的数据。
LINQ主要包含以下三部分:
1、LINQ to Objects 主要负责对象的查询。
2、LINQ to XML 主要负责XML的查询。
3、LINQ to ADO.NET 主要负责数据库的查询。
LINQ to SQL
LINQ to DataSet
LINQ to Entities
三、LINQ的优势
1、熟悉的语言:开发人员不必为每种类型的数据源或数据格式学习新的语言。
2、更少的编码:相比较传统的方式,LINQ减少了要编写的代码量。
3、可读性强:LINQ增加了代码的可读性,因此其他开发人员可以很轻松地理解和维护。
4、标准化的查询方式:可以使用相同的LINQ语法查询多个数据源。
5、类型检查:程序会在编译的时候提供类型检查。
6、智能感知提示:LINQ为通用集合提供智能感知提示。
7、整形数据:LINQ可以检索不同形状的数据。
OfType<>的作用
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqOverCollections
{
#region Simple Car
class Car
{
public string PetName { get; set; }
public string Color { get; set; }
public int Speed { get; set; }
public string Make { get; set; }
}
#endregion
class Program
{
static void Main( string[] args )
{
Console.WriteLine("***** LINQ over Generic Collections *****\n");
// Make a List<> of Car objects.
List<Car> myCars = new List<Car>() {
new Car{ PetName = "Henry", Color = "Silver", Speed = 100, Make = "BMW"},
new Car{ PetName = "Daisy", Color = "Tan", Speed = 90, Make = "BMW"},
new Car{ PetName = "Mary", Color = "Black", Speed = 55, Make = "VW"},
new Car{ PetName = "Clunker", Color = "Rust", Speed = 5, Make = "Yugo"},
new Car{ PetName = "Melvin", Color = "White", Speed = 43, Make = "Ford"}
};
GetFastCars(myCars);
Console.WriteLine();
GetFastBMWs(myCars);
Console.WriteLine();
LINQOverArrayList();
Console.WriteLine();
OfTypeAsFilter();
Console.ReadLine();
}
#region Get fast cars!
static void GetFastCars( List<Car> myCars )
{
// Find all Car objects in the List<>, where the Speed is
// greater than 55.
var fastCars = from c in myCars where c.Speed > 55 select c;
foreach (var car in fastCars)
{
Console.WriteLine("{0} is going too fast!", car.PetName);
}
}
static void GetFastBMWs( List<Car> myCars )
{
// Find the fast BMWs!
var fastCars = from c in myCars where c.Speed > 90 && c.Make == "BMW" select c;
foreach (var car in fastCars)
{
Console.WriteLine("{0} is going too fast!", car.PetName);
}
}
#endregion
#region LINQ over non-generic collection
static void LINQOverArrayList()
{
Console.WriteLine("***** LINQ over ArrayList *****");
// Here is a nongeneric collection of cars.
ArrayList myCars = new ArrayList() {
new Car{ PetName = "Henry", Color = "Silver", Speed = 100, Make = "BMW"},
new Car{ PetName = "Daisy", Color = "Tan", Speed = 90, Make = "BMW"},
new Car{ PetName = "Mary", Color = "Black", Speed = 55, Make = "VW"},
new Car{ PetName = "Clunker", Color = "Rust", Speed = 5, Make = "Yugo"},
new Car{ PetName = "Melvin", Color = "White", Speed = 43, Make = "Ford"}
};
// Transform ArrayList into an IEnumerable<T>-compatible type.
var myCarsEnum = myCars.OfType<Car>();
// Create a query expression targeting the compatible type.
var fastCars = from c in myCarsEnum where c.Speed > 55 select c;
foreach (var car in fastCars)
{
Console.WriteLine("{0} is going too fast!", car.PetName);
}
}
#endregion
#region OfType() filter
static void OfTypeAsFilter()
{
// Extract the ints from the ArrayList.
ArrayList myStuff = new ArrayList();
myStuff.AddRange(new object[] { 10, 400, 8, false, new Car(), "string data" });
var myInts = myStuff.OfType<int>();
// Prints out 10, 400, and 8.
foreach (int i in myInts)
{
Console.WriteLine("Int value: {0}", i);
}
}
#endregion
}
}
延迟执行和立即执行
延迟执行–在迭代之前不会真正执行
立即执行–获取数据快照–操作快照
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqOverArray
{
class Program
{
static void Main( string[] args )
{
Console.WriteLine("***** Fun with LINQ to Objects *****\n");
QueryOverStrings();
Console.WriteLine();
QueryOverStringsLongHand();
Console.WriteLine();
QueryOverInts();
Console.WriteLine();
Console.ReadLine();
}
#region Query over string array
static void QueryOverStrings()
{
// Assume we have an array of strings.
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
// Build a query expression to find the items in the array
// that have an embedded space.
//构建查询表达式以查找数组中的项
//具有嵌入式空间。
IEnumerable<string> subset = from g in currentVideoGames
where g.Contains(" ")
orderby g
select g;
ReflectOverQueryResults(subset);
// Print out the results.
foreach (string s in subset)
Console.WriteLine("Item: {0}", s);
}
#endregion
static void ReflectOverQueryResults( object resultSet )
{
Console.WriteLine("***** Info about your query *****");
Console.WriteLine("resultSet is of type: {0}", resultSet.GetType().Name);
Console.WriteLine("resultSet location: {0}",
resultSet.GetType().Assembly.GetName().Name);
}
#region Query over Int32 array
static void QueryOverInts()
{
int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
// Get numbers less than ten.
var subset = from i in numbers where i < 10 select i;
// LINQ statement evaluated here!
foreach (var i in subset)
Console.WriteLine("{0} < 10", i);
Console.WriteLine();
// Change some data in the array.
numbers[0] = 4;
// Evaluated again!
foreach (var j in subset)
Console.WriteLine("{0} < 10", j);
Console.WriteLine();
ReflectOverQueryResults(subset);
}
#endregion
#region Get strings long hand notation (no LINQ!)
static void QueryOverStringsLongHand()
{
// Assume we have an array of strings.
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
string[] gamesWithSpaces = new string[5];
for (int i = 0; i < currentVideoGames.Length; i++)
{
if (currentVideoGames[i].Contains(" "))
gamesWithSpaces[i] = currentVideoGames[i];
}
// Now sort them.
Array.Sort(gamesWithSpaces);
// Print out the results.
foreach (string s in gamesWithSpaces)
{
if (s != null)
Console.WriteLine("Item: {0}", s);
}
Console.WriteLine();
}
#endregion
#region Immediate execution 立即执行
static void ImmediateExecution()
{
int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
// Get data RIGHT NOW as int[].
int[] subsetAsIntArray =
(from i in numbers where i < 10 select i).ToArray<int>();
// Get data RIGHT NOW as List<int>.
List<int> subsetAsListOfInts =
(from i in numbers where i < 10 select i).ToList<int>();
}
#endregion
}
}
查询案例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunWithLinqExpressions
{
#region Product class
class ProductInfo
{
public string Name { get; set; }
public string Description { get; set; }
public int NumberInStock { get; set; }
public override string ToString()
{
return string.Format("Name={0}, Description={1}, Number in Stock={2}",
Name, Description, NumberInStock);
}
}
#endregion
class Program
{
static void Main( string[] args )
{
Console.WriteLine("***** Fun with Query Expressions *****\n");
// This array will be the basis of our testing...
ProductInfo[] itemsInStock = new[] {
new ProductInfo{ Name = "Mac's Coffee",
Description = "Coffee with TEETH",
NumberInStock = 24},
new ProductInfo{ Name = "Milk Maid Milk",
Description = "Milk cow's love",
NumberInStock = 100},
new ProductInfo{ Name = "Pure Silk Tofu",
Description = "Bland as Possible",
NumberInStock = 120},
new ProductInfo{ Name = "Cruchy Pops",
Description = "Cheezy, peppery goodness",
NumberInStock = 2},
new ProductInfo{ Name = "RipOff Water",
Description = "From the tap to your wallet",
NumberInStock = 100},
new ProductInfo{ Name = "Classic Valpo Pizza",
Description = "Everyone loves pizza!",
NumberInStock = 73}
};
// We will call various methods here!
SelectEverything(itemsInStock);
Console.WriteLine();
ListProductNames(itemsInStock);
Console.WriteLine();
GetOverstock(itemsInStock);
Console.WriteLine();
GetNamesAndDescriptions(itemsInStock);
Console.WriteLine();
GetProjectedSubset(itemsInStock);
Console.WriteLine();
Array objs = GetProjectedSubset(itemsInStock);
foreach (object o in objs)
{
Console.WriteLine(o); // Calls ToString() on each anonymous object.
}
Console.WriteLine();
GetCountFromQuery();
Console.WriteLine();
ReverseEverything(itemsInStock);
Console.WriteLine();
AlphabetizeProductNames(itemsInStock);
Console.WriteLine();
DisplayDiff();
Console.WriteLine();
DisplayIntersection();
Console.WriteLine();
DisplayUnion();
Console.WriteLine();
DisplayConcat();
Console.WriteLine();
DisplayConcatNoDups();
Console.WriteLine();
AggregateOps();
Console.ReadLine();
}
#region Select everything
static void SelectEverything( ProductInfo[] products )
{
// Get everything!
Console.WriteLine("All product details:");
var allProducts = from p in products select p;
foreach (var prod in allProducts)
{
Console.WriteLine(prod.ToString());
}
}
#endregion
#region Only get Names
static void ListProductNames( ProductInfo[] products )
{
// Now get only the names of the products.
Console.WriteLine("Only product names:");
var names = from p in products select p.Name;
foreach (var n in names)
{
Console.WriteLine("Name: {0}", n);
}
}
#endregion
#region Get object subset
static void GetOverstock( ProductInfo[] products )
{
Console.WriteLine("The overstock items!");
// Get only the items where we have more than
// 25 in stock.
var overstock = from p in products where p.NumberInStock > 25 select p;
foreach (ProductInfo c in overstock)
{
Console.WriteLine(c.ToString());
}
}
#endregion
#region LINQ projections
static void GetNamesAndDescriptions( ProductInfo[] products )
{
Console.WriteLine("Names and Descriptions:");
var nameDesc = from p in products select new { p.Name, p.Description };
foreach (var item in nameDesc)
{
// Could also use Name and Description properties directly.
Console.WriteLine(item.ToString());
}
}
static Array GetProjectedSubset( ProductInfo[] products )
{
var nameDesc = from p in products select new { p.Name, p.Description };
return nameDesc.ToArray();
}
#endregion
#region Get count
static void GetCountFromQuery()
{
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
// Get count from the query.
int numb =
(from g in currentVideoGames where g.Length > 6 select g).Count();
// Print out the number of items.
Console.WriteLine("{0} items honor the LINQ query.", numb);
}
#endregion
#region Show results in reverse
static void ReverseEverything( ProductInfo[] products )
{
Console.WriteLine("Product in reverse:");
var allProducts = from p in products select p;
foreach (var prod in allProducts.Reverse())
{
Console.WriteLine(prod.ToString());
}
}
#endregion
#region OrderBy
static void AlphabetizeProductNames( ProductInfo[] products )
{
// Get names of products, alphabetized.
var subset = from p in products orderby p.Name select p;
Console.WriteLine("Ordered by Name:");
foreach (var p in subset)
{
Console.WriteLine(p.ToString());
}
}
#endregion
#region Except(), Intersect(), Union(), Concat()
static void DisplayDiff()
{
List<string> myCars = new List<String> { "Yugo", "Aztec", "BMW" };
List<string> yourCars = new List<String> { "BMW", "Saab", "Aztec" };
var carDiff = (from c in myCars select c)
.Except(from c2 in yourCars select c2);
Console.WriteLine("Here is what you don't have, but I do:");
foreach (string s in carDiff)
Console.WriteLine(s); // Prints Yugo.
}
static void DisplayIntersection()
{
List<string> myCars = new List<String> { "Yugo", "Aztec", "BMW" };
List<string> yourCars = new List<String> { "BMW", "Saab", "Aztec" };
// Get the common members.
var carIntersect = (from c in myCars select c)
.Intersect(from c2 in yourCars select c2);
Console.WriteLine("Here is what we have in common:");
foreach (string s in carIntersect)
Console.WriteLine(s); // Prints Aztec and BMW.
}
static void DisplayUnion()
{
List<string> myCars = new List<String> { "Yugo", "Aztec", "BMW" };
List<string> yourCars = new List<String> { "BMW", "Saab", "Aztec" };
// Get the union of these containers.
var carUnion = (from c in myCars select c)
.Union(from c2 in yourCars select c2);
Console.WriteLine("Here is everything:");
foreach (string s in carUnion)
Console.WriteLine(s); // Prints all common members
}
static void DisplayConcat()
{
List<string> myCars = new List<String> { "Yugo", "Aztec", "BMW" };
List<string> yourCars = new List<String> { "BMW", "Saab", "Aztec" };
var carConcat = (from c in myCars select c)
.Concat(from c2 in yourCars select c2);
// Prints:
// Yugo Aztec BMW BMW Saab Aztec.
Console.WriteLine("Here is CONCAT");
foreach (string s in carConcat)
Console.WriteLine(s);
}
static void DisplayConcatNoDups()
{
List<string> myCars = new List<String> { "Yugo", "Aztec", "BMW" };
List<string> yourCars = new List<String> { "BMW", "Saab", "Aztec" };
var carConcat = (from c in myCars select c)
.Concat(from c2 in yourCars select c2);
// Prints:
// Yugo Aztec BMW Saab Aztec.
foreach (string s in carConcat.Distinct())
Console.WriteLine(s);
}
#endregion
#region Agg Ops
static void AggregateOps()
{
double[] winterTemps = { 2.0, -21.3, 8, -4, 0, 8.2 };
// Various aggregation examples.
Console.WriteLine("Max temp: {0}",
(from t in winterTemps select t).Max());
Console.WriteLine("Min temp: {0}",
(from t in winterTemps select t).Min());
Console.WriteLine("Avarage temp: {0}",
(from t in winterTemps select t).Average());
Console.WriteLine("Sum of all temps: {0}",
(from t in winterTemps select t).Sum());
}
#endregion
}
}
使用表达式查询
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqUsingEnumerable
{
class VeryComplexQueryExpression
{
public static void QueryStringsWithRawDelegates()
{
Console.WriteLine("***** Using Raw Delegates *****");
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
// Build the necessary Func<> delegates.
Func<string, bool> searchFilter = new Func<string, bool>(Filter);
Func<string, string> itemToProcess = new Func<string, string>(ProcessItem);
// Pass the delegates into the methods of Enumerable.
var subset = currentVideoGames
.Where(searchFilter).OrderBy(itemToProcess).Select(itemToProcess);
// Print out the results.
foreach (var game in subset)
Console.WriteLine("Item: {0}", game);
Console.WriteLine();
}
// Delegate targets.
public static bool Filter( string game ) { return game.Contains(" "); }
public static string ProcessItem( string game ) { return game; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqUsingEnumerable
{
class Program
{
static void Main( string[] args )
{
Console.WriteLine("***** LINQ: Simple to WAY Complex *****\n");
QueryStringWithOperators();
Console.WriteLine();
QueryStringsWithEnumerableAndLambdas();
Console.WriteLine();
QueryStringsWithAnonymousMethods();
Console.WriteLine();
VeryComplexQueryExpression.QueryStringsWithRawDelegates();
Console.ReadLine();
}
#region LINQ operators
static void QueryStringWithOperators()
{
Console.WriteLine("***** Using Query Operators *****");
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
var subset = from game in currentVideoGames
where game.Contains(" ")
orderby game
select game;
foreach (string s in subset)
Console.WriteLine("Item: {0}", s);
}
#endregion
#region LINQ using Enumerable and =>
static void QueryStringsWithEnumerableAndLambdas()
{
Console.WriteLine("***** Using Enumerable / Lambda Expressions *****");
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
// Build a query expression using extension methods
// granted to the Array via the Enumerable type.
var subset = currentVideoGames.Where(game => game.Contains(" "))
.OrderBy(game => game).Select(game => game);
// Print out the results.
foreach (var game in subset)
Console.WriteLine("Item: {0}", game);
Console.WriteLine();
}
static void QueryStringsWithEnumerableAndLambdas2()
{
Console.WriteLine("***** Using Enumerable / Lambda Expressions (version 2) *****");
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
// Break it down!
var gamesWithSpaces = currentVideoGames.Where(game => game.Contains(" "));
var orderedGames = gamesWithSpaces.OrderBy(game => game);
var subset = orderedGames.Select(game => game);
foreach (var game in subset)
Console.WriteLine("Item: {0}", game);
Console.WriteLine();
}
#endregion
#region LINQ using anon methods
static void QueryStringsWithAnonymousMethods()
{
Console.WriteLine("***** Using Anonymous Methods *****");
string[] currentVideoGames = {"Morrowind", "Uncharted 2",
"Fallout 3", "Daxter", "System Shock 2"};
// Build the necessary Func<> delegates using anonymous methods.
Func<string, bool> searchFilter =
delegate( string game ) { return game.Contains(" "); };
Func<string, string> itemToProcess = delegate( string s ) { return s; };
// Pass the delegates into the methods of Enumerable.
var subset = currentVideoGames.Where(searchFilter)
.OrderBy(itemToProcess).Select(itemToProcess);
// Print out the results.
foreach (var game in subset)
Console.WriteLine("Item: {0}", game);
Console.WriteLine();
}
#endregion
}
}