【翻译】Pro LINQ Language Integrated Query in C# 2008 -- 第一章,第二节
最近在看这本书,特翻译书中部分内容。
LINQ不只是为了查询
或许通过定义你认为LINQ是为了查询,因为它代表语言继承查询。但是请不要这么想。它已经超出了单纯的数据查询。
我更喜欢认为LINQ是一个数据迭代引擎,但是也许Microsoft不像将这个技术命名为DIE。
你曾经调用一个方法并且返回一些数据结构中的数据,然后需要在调用之前它传递给另一个方法将其转换为另一个数据结构?让我们假设例如您调用方法 A ,并且A 方法返回一个包含数字存储的字符串类型。 然后您需要调用方法 B,但方法 B 要求为整数数组。
示例1-4. 转换一个字符串数组为整型数组
这个例子,我将声明一个字符串数组。现在在调用方法B之前,我需要转换字符串数组为一个整型数组:
这里。是不是很简单?下面的代码是来显示整数数组的结果:
Console.WriteLine(num);
运行结果:
42
10
9
27
我知道你可能会想:可能我只是去掉了前导零。如果我要排序他,你要如何要我信服?如果他们依然存字符串,9也会在10的后面。示例 1-5 代码实现了进行转换并对其进行排序输出。
示例 1-5. 将字符串数组转换成数字数组并排序
int[] nums = numbers.Select(s => Int32.Parse(s)).OrderBy(s => s).ToArray();
foreach(int num in nums)
Console.WriteLine(num);
运行结果:
9
10
27
42
那多巧妙?OK,你会说简直太棒了,但是这确实是一个简单的例子。现在我将给你一个更复杂的例子。
让我们假设你有一些Employee类中的Common代码。Employee类中有一个方法返回所有雇员。你还需要Contact类中的Common底层代码,并且这个方法是为了发布所有联系人。我们来假设你要分配所有雇员为联系人。
该任务看上去简单,但是他抓住了一个关键点。这个Common的Employee方法中取出一个装有Employee的ArrayList对象从而获取所有雇员,并且Contact发布联系人方法获取一个Contact类型的数组。Common代码如下:
{
public class Employee
{
public int id;
public string firstName;
public string lastName;
public static ArrayList GetEmployees()
{
// Of course the real code would probably be making a database query
// right about here.
ArrayList al = new ArrayList();
// Man, do the new C# object initialization features make this a snap.
al.Add(new Employee { id = 1, firstName = "Joe", lastName = "Rattz"} );
al.Add(new Employee { id = 2, firstName = "William", lastName = "Gates"} );
al.Add(new Employee { id = 3, firstName = "Anders", lastName = "Hejlsberg"} );
return(al);
}
}
}
namespace LINQDev.Common
{
public class Contact
{
public int Id;
public string Name;
public static void PublishContacts(Contact[] contacts)
{
// This publish method just writes them to the console window.
foreach(Contact c in contacts)
Console.WriteLine("Contact Id: {0} Contact: {1}", c.Id, c.Name);
}
}
}
正如你所看到的,Employee类和GetEmployees方法都在同一个LINQDev.HR命名空间中,并且GetEmployees方法返回一个ArrayList。PublishContacts方法在另一个LINQDev.Common命名空间中,并且传入一个Contact对象数组。
以前,这意味着要由GetEmployees 方法循环 ArrayList ,并创建一个新的Contact类型数组传递给 PublishContacts 方法。
LINQ是它变得简单,就像示例 1-6.
示例 1-6 调用Common代码
LINQDev.Common.Contact[] contacts = alEmployees.Cast<LINQDev.HR.Employee>()
.Select(e => new LINQDev.Common.Contact {
Id = e.id,
Name = string.Format("{0} {1}", e.firstName, e.lastName)
})
.ToArray<LINQDev.Common.Contact>();
LINQDev.Common.Contact.PublishContacts(contacts);
转换Employee对象的ArrayList 为Contact对象数组,我首先将Employee对象的ArrayList使用Cast Standard Query Operator转换成一个IEnumerable<Employee>序列。这是必须的,因为要使用旧的ArrayList集合类。语法上说,ArrayList是存储System.Object 类 类型对象。所以我必须转换Employee对象。我们不必使得 GetEmployees 方法返回泛型列表集合。但是,该集合类型没有用旧代码便已写入。
下来,我要调用那个Select操作返回Employee序列并且使用Lambda语法,代码调用Select方法传递,我使用新的C# 3.0 对象实例化特性来实例化并初始化一个Contact对象,并将输入Employee类的项值分配到一个新构造输出Contact类的项。
Lambda表达式是 C# 3.0 的新特性,它允许指定匿名方法。在后面会有详细介绍。最后,我使用ToArray操作将新构造 Contact 对象序列转换成一个Contact对象数组,因为它是PublishContacts方法需要的。是不是很巧妙呢?
运行结果:
Contact Id: 1 Contact: Joe Rattz
Contact Id: 2 Contact: William Gates
Contact Id: 3 Contact: Anders Hejlsberg
就像你看到的,LINQ 不仅仅是数据查询。 你通过阅读这本书的相关章节后,尝试考虑 LINQ 提供的功能的其他用途。