Lambda Expressions

无论是expression lambda还是statement lambda,都适用以下的描述:

Lambda Expressions - This is a shorthand for specifying a method. The C# compiler will translate each into either an anonymous method or a true System.Linq.Expressions.Expression. You really need to understand these to use Linq well. There are three parts: A parameter list, an arrow, and a method body.

 

1.匿名方法的例子:(匿名方法可以作为delegate直接传给接受Action<>,Func<>这些concrete delegate的地方,也就是编译器可以自动转换,但如果接受方需要的是Delegate这个抽象的类对象,比如Dispatch.Invoke方法,就要类型转换,这里有讨论这个问题的。)

new Action(() =>{...})

lambda表达式变成了 .method public hidebysig instance void <LoadData>b__8() cil managed

    <>c__DisplayClassa CS$<>8__localsb; (这里Reflector翻译的C#不准,看IL指令集,实际是newobj指令,把当前context创建出来)
      CS$<>9__CachedAnonymousMethodDelegate9 = new Action(CS$<>8__localsb, (IntPtr) this.<LoadData>b__8);
(调用了Lambda表达式形成的匿名方法)

 

2.转成Expressions的例子,生成了暴多的IL,应用了很多Expressons命名空间的类和方法:

h => h.CompanyCode == "1"  会变成 Expression<Func<T, bool>> expr

: ldtoken [CdcSoftware.Erp.RuntimeServices]CdcSoftware.Erp.RuntimeServices.Entities.Finance.SalesOrderHeader
    L_0012: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
    L_0017: ldstr "h"
    L_001c: call class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type, string)
    L_0021: stloc.3
    L_0022: ldloc.3
    L_0023: ldtoken instance string [CdcSoftware.Erp.RuntimeServices]CdcSoftware.Erp.RuntimeServices.Entities.Finance.SalesOrderHeader::get_CompanyCode()
    L_0028: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
    L_002d: castclass [mscorlib]System.Reflection.MethodInfo
    L_0032: call class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression, class [mscorlib]System.Reflection.MethodInfo)
    L_0037: ldstr "1"
    L_003c: ldtoken string
    L_0041: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
    L_0046: call class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object, class [mscorlib]System.Type)
    L_004b: ldc.i4.0
    L_004c: ldtoken bool [mscorlib]System.String::op_Equality(string, string)
    L_0051: call class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
    L_0056: castclass [mscorlib]System.Reflection.MethodInfo
    L_005b: call class [System.Core]System.Linq.Expressions.BinaryExpression [System.Core]System.Linq.Expressions.Expression::Equal(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.Expression, bool, class [mscorlib]System.Reflection.MethodInfo) //这时栈内是第一个参数,lambda的body Expression
    L_0060: ldc.i4.1
    L_0061: newarr [System.Core]System.Linq.Expressions.ParameterExpression
    L_0066: stloc.s CS$0$0002
    L_0068: ldloc.s CS$0$0002
    L_006a: ldc.i4.0
    L_006b: ldloc.3
    L_006c: stelem.ref
    L_006d: ldloc.s CS$0$0002 //把ParameterExpression[0]加载到栈里(第二个参数,lambda的左边的参数集合)
    L_006f: call class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class [CdcSoftware.Erp.RuntimeServices]CdcSoftware.Erp.RuntimeServices.Entities.Finance.SalesOrderHeader, bool>>(class [System.Core]System.Linq.Expressions.Expression, class [System.Core]System.Linq.Expressions.ParameterExpression[])

题外话:关于IL的参数顺序,生成的IL都是从左到右压到栈里的,但为什么网上都说c#是stdcall呢(也是从右到左的)。这里指出:“当我们使用 call 等指令调用一个方法时,CLR 为目标方法在调用堆栈上新分配一个堆栈帧,并将方法参数从当前方法的计算堆栈弹出压入目标方法的参数表中,接着执行流程跳转到目标方法。”注意弹出压入一词,在老方法里压栈的顺序是param1,param2,则老栈内是param2在param1上面 弹出压入新参数表栈后,由于是param2先弹压,就变成了param2在param1下面了。这就是从右到左的过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值