C#3.0有很多值得学习的地方,这里我们主要介绍Linq查询,包括介绍Linq Lambda表达式等方面。
C#3.0时代的Linq查询语句
在C#3.0中我们又有了改善代码的新工具。
匿名委托很不错,但是我们希望有更简单的,更容易维护的代码。C#3.0提供了Linq Lambda表达式的概念,你可以把Linq Lambda表达式是我们应用匿名委托的捷径,下面是用Linq Lambda表达式重写的查询:
static IEnumerable<Employee>
GoldWatch(IEnumerable<Employee> employees) {
return Filter(employees,
employee => employee.Years>3
);
}
static IEnumerable<Employee>
SalesForce(IEnumerable<Employee> employees) {
return Filter(employees,
employee => employee.Department=="Sales"
);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
这段代码相当简单而且也很容易维护,但还存在一些问题。
◆GoldWatch(employees)
◆SalesForce(employees)
当你看到这样的调用的时候就会意识到这个问题,从OO的视角来看,我们已经熟悉了noun.verb()这样的调用形式,理想情况下,我们希望用这样的语法能查询一个集合:
◆employees.GoldWatch()
◆employees.SalesForce()
有人可能会定义一个新的Employee类,它实现了IEnumerable<Employee>。但是问题是,我们的用户可能会希望是用别的 IEnumerable<Employee>实现,比如Employee[]和List<Employee>。
C#3.0用扩展方法(Extension method)解决这个方法:
static IEnumerable<Employee>
Filter(this IEnumerable<Employee> employees, Choose choose) {
foreach (Employee employee in employees) {
if (choose(employee)) {
yield return employee;
}
}
}
static IEnumerable<Employee>
GoldWatch(this IEnumerable<Employee> employees) {
return employees.Filter(employee => employee.Years>3);
}
static IEnumerable<Employee>
SalesForce(this IEnumerable<Employee> employees) {
return employees.Filter(
employee => employee.Department=="Sales");
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
这看起来很好了,但如果我们想象Employee一样查询Customer呢?或者说,查询我们的存货呢?
不用为每一个类单独写一个Filter方法,我们可以将Filter写成一个通用函数:
delegate bool Choose<T>(T t);
static IEnumerable<T>
Filter<T>(this IEnumerable<T> items, Choose<T> choose) {
foreach (T item in items) {
if (choose(item)) {
yield return item;
}
}
}
//现在我们可以筛选我们希望的任何类型了!
int [] a = new int [] {1,2,3,4,5};
a.Filter(i => i==1 || i==3);
//这个筛选方法是如此有用且通用,C#里已经内置了一个称为Where的实现
//在PDC上展示的实际的Where实现
public delegate T Func<A0, T>(A0 arg0);
public static
IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, bool> predicate) {
foreach (T element in source) {
if (predicate(element)) yield return element;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
【编辑推荐】