VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • LINQ系列之基础与本质(三)

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

  前面我们对LINQ的本质,以及MS针对LINQ对3.5新增的几个类做了分析。作为本系列的第一篇:基础与本质的最后一篇,我想对Lambda表达式讲解一下。本来Lambda表达式也可以放到系列c#3.x学习中,我想还是放到LINQ系列比较好讲一些。

  1 Lambda表达式例子

  先来熟悉一下Lambda的一般样子,代码:

1 x => x * 2;
2 (x, y) => x * 10 + y;
3 (x, y, z) => (1 / x + 10) * y + z;
4 Func<int, int> f1;
5 f1 = x => x * 2;
6 Func<int, int, int> f2;
7 f2 = (x, y) => x * 10 + y;
8 Func<int, int, int, int> f3;
9 f3 = (x, y, z) => (1 / x + 10) * y + z;
10 // A lambda expression with no arguments
11 Func<int> f4 = ()=> 10;
12 int r1 = f1(10);
13 int r2 = f2(5, 10);

  这些是C#3.0新特性为Lambda定义的格式。

Func<int, int> f1 = x => x * 2;<=> Func<int, int> f1 = delegate(int x){return x * 2;};

  我们说这两种方式可以说在某种情况下是等价的,为什么等价的呢?请看本文的第二部分的分析。

  2 Lambda 表达本质

  Lambda 表达式可以用在任何需要使用匿名方法,或是代理的地方。我们看看下面的代码:

1 List<int> numbers = new List<int>{ 10, 20, 28, 40, 1, 3, 5, 8 };
2 List<int> evenNumbers = numbers.FindAll( i => ( i % 2 ) == 0 );
3 List<int> evenNumbers1 = numbers.FindAll( delegate( int i )
4 {
5  return ( i % 2 ) == 0;
6 } );

 

  我们通过Reflector工具可以看到编译器会将Lambda表达式编译为标准的匿名方法。下面是在Reflector下看到的代码:

1 List<int> evenNumbers = numbers.FindAll(delegate (int i) {
2     return (i % 2) == 0;
3   });
4 List<int> evenNumbers1 = numbers.FindAll(delegate (int i) {
5     return (i % 2) == 0;
6   });

  现在看看他们的IL:

1 L_0060: ldftn bool LINQProject.test2::<TestLambda>b__1(int32)
2 L_0066: newobj instance void [mscorlib]System.Predicate`1<int32>::.ctor(object, native int)
3 L_006b: stsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate3
4 L_0070: br.s L_0072
5 L_0072: ldsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate3
6 L_0077: callvirt instance class [mscorlib]System.Collections.Generic.List`1<!0> [mscorlib]System.Collections.Generic.List`1<int32>::FindAll(class [mscorlib]System.Predicate`1<!0>)
7 L_007c: stloc.1
8 L_007d: ldloc.0
9 L_007e: ldsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate4
10 L_0083: brtrue.s L_0098
11 L_0085: ldnull
12 L_0086: ldftn bool LINQProject.test2::<TestLambda>b__2(int32)
13 L_008c: newobj instance void [mscorlib]System.Predicate`1<int32>::.ctor(object, native int)
14 L_0091: stsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate4
15 L_0096: br.s L_0098
16 L_0098: ldsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate4
17 L_009d: callvirt instance class [mscorlib]System.Collections.Generic.List`1<!0> [mscorlib]System.Collections.Generic.List`1<int32>::FindAll(class [mscorlib]System.Predicate`1<!0>)
18 L_00a2: stloc.2

 

  通过对Lambda表达式的IL的分析是编译器自动生成相应的静态成员和静态方法,带来着一些的都是编译器,CLR并没有做出实质的改变,这就更加验证了上一篇文章的说明,委托,匿名方法,Lambda表达式都是一脉相承的,实现原理都是通过委托。

  3 Lambda表达式的分析

  MS定义Lambda表达式的标准写法为:

ArgumentsToProcess => StatementsToProcess

  被编译器编译为:

inputs (delegate parameters) =>Expression to be evaluated(expression return must match delegate return value type)

  其中=>为Lambda的操作符。

  比如前面的代码:List<int> evenNumbers = numbers.FindAll( i => ( i % 2 ) == 0 );我们可以理解为:List<int> evenNumbers = numbers.FindAll( (i) => (( i % 2 ) == 0 ));我们也可以现实的指示输入参数的类型。当有有多行处理表达式时,需要使用大括号包起来,例如:

  Code

List<int> evenNumbers = list.FindAll((i) =>
{
Console.WriteLine("value: {0}", i);
bool isRig = ((i % 2) == 0);
return isRig;
});
当输入参数有多个时:

  Code

VerySimpleDelegate d = new VerySimpleDelegate( (x,y) => {Console.WriteLine(x-y);} );

  当没有参数的时候:()里面可以为空。

  局部变量也可以在Lambda表达式中使用,例如

  Code

1 double y = 0;
2 Func<double, double> t = x => x * y;
3 double r1 = t(10);
4 y = 10;
5 double r2 = t(10);

 

  我们通过Reflector工具可以看到编译器会将Lambda表达式编译为标准的匿名方法。下面是在Reflector下看到的代码:

1 List<int> evenNumbers = numbers.FindAll(delegate (int i) {
2     return (i % 2) == 0;
3   });
4 List<int> evenNumbers1 = numbers.FindAll(delegate (int i) {
5     return (i % 2) == 0;
6   });

  现在看看他们的IL:

1 L_0060: ldftn bool LINQProject.test2::<TestLambda>b__1(int32)
2 L_0066: newobj instance void [mscorlib]System.Predicate`1<int32>::.ctor(object, native int)
3 L_006b: stsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate3
4 L_0070: br.s L_0072
5 L_0072: ldsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate3
6 L_0077: callvirt instance class [mscorlib]System.Collections.Generic.List`1<!0> [mscorlib]System.Collections.Generic.List`1<int32>::FindAll(class [mscorlib]System.Predicate`1<!0>)
7 L_007c: stloc.1
8 L_007d: ldloc.0
9 L_007e: ldsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate4
10 L_0083: brtrue.s L_0098
11 L_0085: ldnull
12 L_0086: ldftn bool LINQProject.test2::<TestLambda>b__2(int32)
13 L_008c: newobj instance void [mscorlib]System.Predicate`1<int32>::.ctor(object, native int)
14 L_0091: stsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate4
15 L_0096: br.s L_0098
16 L_0098: ldsfld class [mscorlib]System.Predicate`1<int32> LINQProject.test2::CS$<>9__CachedAnonymousMethodDelegate4
17 L_009d: callvirt instance class [mscorlib]System.Collections.Generic.List`1<!0> [mscorlib]System.Collections.Generic.List`1<int32>::FindAll(class [mscorlib]System.Predicate`1<!0>)
18 L_00a2: stloc.2



相关教程