Linq有很多值得学习的地方,这里我们主要介绍Lambda表达式和Linq查询,包括介绍Filter方法等方面。
Lambda表达式和Linq查询
接下来我们通过一个例子来看一下Lambda表达式和Linq查询的关系:我们现在想给ClassCollection增加一个过滤方法,方法的目的是能够过滤返回班级名称为“终极一班”的集合来。
1.首先给MyExtention增加这么一个静态方法:
public static ClassCollection Filter(this ClassCollection classes)
{
var newnewlist = new ClassCollection();
foreach (var item in classes)
{
if (item.Name=="终极一班")
{
newlist.Add(item);
}
}
return newlist;
}
private static void LambdaLinq()
{
var classes = GetClasses();
//var students = GetStudents();
//0 原始版本
var result = classes.Filter();
foreach (var item in result)
}
Console.WriteLine(item.ID+ " " + item.Name);
}
}
//相关的工厂方法:
static ClassCollection GetClasses()
{
return new ClassCollection{
new Class(1){ Name = "终极一班"},
new Class(2){ Name = "终极二班"},
};
}
- 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.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
2.现在需求发生了变化,需要上面的红色部分需要发生变化,也就是说我们希望这个查询条件可以在我们调用Filter方法的时候动态的指定,这时候我们可以把这个变化封装成一个接口,当然还可以封装成一个委托,这是.net的非常好用的独有特性,委托的最直接的作用可以把一个具体的方法引用封装成一个变量传递。好,开始变形!
delegate bool FilterHandler(Class c);
//注意这个要放到namespace下面,不要放到Program类里面
public static ClassCollection Filter(this ClassCollection classes,FilterHandler f)
{
var newnewlist = new ClassCollection();
foreach (var item in classes)
{
if (f(item))
{
newlist.Add(item);
}
}
return newlist;
}
static bool F(Class c)
{
return c.Name == "终极一班";
}
private static void LambdaLinq()
{
var classes = GetClasses();
// C#1.0 使用委托封装过滤条件
FilterHandler f=new FilterHandler(F);
var result = classes.Filter(f);
foreach (var item in result)
{
Console.WriteLine(item.ID+ " " + item.Name);
}
}
- 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.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
我们声明了一个委托FilterHandler,只要满足这个委托的方法我们都可以传递给Filter方法,这样就实现了动态的改变查询条件的目的,F方法内部可以是任意的查询条件比如return c.Name != "终极一班";同时我们不需要改变Filter方法内部稳定的部分。
3.c#2.0里面也支持直接把一个方法传给一个委托,但本质上也是编译器把方法转换成了一个委托,例如上面:
private static void LambdaLinq()
{
var classes = GetClasses();
// C#2.0 直接传递方法
var result = classes.Filter(F);
foreach (var item in result)
{
Console.WriteLine(item.ID+ " " + item.Name);
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
4.C#2.0里面有个新特性,叫匿名方法,我们可以直接传递匿名方法:
private static void LambdaLinq()
{
var classes = GetClasses();
// C#2.0 传递匿名方法
var result = classes.Filter(delegate(Class c) { return c.Name == "终极一班"; });
foreach (var item in result)
{
Console.WriteLine(item.ID+ " " + item.Name);
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
好,变形到这里,我们发现这个匿名其实不仅仅可以给我们带来不用给方法命名的好处,在这个方法内部我们还可以使用外部上下文环境的变量成员,这个特性也叫“闭包(Closure)”,JavaScript也支持这个特性,比如:
private static void LambdaLinq()
{
var classes = GetClasses();
string className = "终极一班";
// C#2.0 传递匿名方法
var result = classes.Filter(delegate(Class c) { return c.Name == className; });
foreach (var item in result)
{
Console.WriteLine(item.ID+ " " + item.Name);
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
以上介绍Lambda表达式和Linq查询。
【编辑推荐】