c# – LINQ序列 – 它们如何在IL中链接?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – LINQ序列 – 它们如何在IL中链接?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6040字,纯文字阅读大概需要9分钟。
内容图文
![c# – LINQ序列 – 它们如何在IL中链接?](/upload/InfoBanner/zyjiaocheng/812/6fa21379299b4e7fa122f64474f29dd7.jpg)
无论我使用表达式查询语法还是方法语法,IL看起来几乎都是一样的.
将LINQ查询作为“渐进式语法”执行:
IEnumerable<Employee> query1 = _employees.Where(e => e.Location.Equals("California"));
IEnumerable<Employee> query2 = query1.OrderByDescending(e => e.Name);
IEnumerable<string> query3 = query2.Select(e => e.Name);
产生:
IL_0001: ldarg.0 // this
IL_0002: ldfld class [mscorlib]System.Collections.Generic.IList`1<class Fundamentals.LINQ.Employee> Fundamentals.LINQ.Syntax::_employees
IL_0007: ldsfld class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, bool> Fundamentals.LINQ.Syntax/'<>c'::'<>9__3_0'
IL_000c: dup
IL_000d: brtrue.s IL_0026
IL_000f: pop
IL_0010: ldsfld class Fundamentals.LINQ.Syntax/'<>c' Fundamentals.LINQ.Syntax/'<>c'::'<>9'
IL_0015: ldftn instance bool Fundamentals.LINQ.Syntax/'<>c'::'<TestMethodSyntaxProgressive>b__3_0'(class Fundamentals.LINQ.Employee)
IL_001b: newobj instance void class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, bool>::.ctor(object, native int)
IL_0020: dup
IL_0021: stsfld class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, bool> Fundamentals.LINQ.Syntax/'<>c'::'<>9__3_0'
IL_0026: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0/*class Fundamentals.LINQ.Employee*/> [System.Core]System.Linq.Enumerable::Where<class Fundamentals.LINQ.Employee>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0/*class Fundamentals.LINQ.Employee*/>, class [mscorlib]System.Func`2<!!0/*class Fundamentals.LINQ.Employee*/, bool>)
IL_002b: stloc.0 // query1
// [100 13 - 100 82]
IL_002c: ldloc.0 // query1
IL_002d: ldsfld class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, string> Fundamentals.LINQ.Syntax/'<>c'::'<>9__3_1'
IL_0032: dup
IL_0033: brtrue.s IL_004c
IL_0035: pop
IL_0036: ldsfld class Fundamentals.LINQ.Syntax/'<>c' Fundamentals.LINQ.Syntax/'<>c'::'<>9'
IL_003b: ldftn instance string Fundamentals.LINQ.Syntax/'<>c'::'<TestMethodSyntaxProgressive>b__3_1'(class Fundamentals.LINQ.Employee)
IL_0041: newobj instance void class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, string>::.ctor(object, native int)
IL_0046: dup
IL_0047: stsfld class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, string> Fundamentals.LINQ.Syntax/'<>c'::'<>9__3_1'
IL_004c: call class [System.Core]System.Linq.IOrderedEnumerable`1<!!0/*class Fundamentals.LINQ.Employee*/> [System.Core]System.Linq.Enumerable::OrderByDescending<class Fundamentals.LINQ.Employee, string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0/*class Fundamentals.LINQ.Employee*/>, class [mscorlib]System.Func`2<!!0/*class Fundamentals.LINQ.Employee*/, !!1/*string*/>)
IL_0051: stloc.1 // query2
// [101 13 - 101 69]
IL_0052: ldloc.1 // query2
IL_0053: ldsfld class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, string> Fundamentals.LINQ.Syntax/'<>c'::'<>9__3_2'
IL_0058: dup
IL_0059: brtrue.s IL_0072
IL_005b: pop
IL_005c: ldsfld class Fundamentals.LINQ.Syntax/'<>c' Fundamentals.LINQ.Syntax/'<>c'::'<>9'
IL_0061: ldftn instance string Fundamentals.LINQ.Syntax/'<>c'::'<TestMethodSyntaxProgressive>b__3_2'(class Fundamentals.LINQ.Employee)
IL_0067: newobj instance void class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, string>::.ctor(object, native int)
IL_006c: dup
IL_006d: stsfld class [mscorlib]System.Func`2<class Fundamentals.LINQ.Employee, string> Fundamentals.LINQ.Syntax/'<>c'::'<>9__3_2'
IL_0072: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1/*string*/> [System.Core]System.Linq.Enumerable::Select<class Fundamentals.LINQ.Employee, string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0/*class Fundamentals.LINQ.Employee*/>, class [mscorlib]System.Func`2<!!0/*class Fundamentals.LINQ.Employee*/, !!1/*string*/>)
IL_0077: stloc.2 // query3
根据LINQ的工作方式,Where()操作的输出序列应该成为OrderByDescending()的输入序列,第二个输出序列应该流入Select().我只是无法理解哪些IL代码与之对应.
这是神奇的部分吗?
IL_002b: stloc.0 // query1
// [100 13 - 100 82]
IL_002c: ldloc.0 // query1
如果我将LINQ查询作为’流利’:
IEnumerable<string> names = _employees.Where(e => e.Location.Equals("California")).OrderByDescending(e => e.Name).Select(e => e.Name);
我没有得到stloc.0,ldloc.0指令.这是“渐进式语法”和“渐进式语法”之间IL发出的唯一差异. ‘流利的语法’. JIT编译器中是否有第二步生成额外的IL指令来执行序列输入?
解决方法:
两个版本之间的唯一区别是本地人.在第一个版本中,每个调用的返回值都保存到本地,然后在该本地调用下一个方法,依此类推.
我假设你问的是当没有当地人时它是如何运作的?方法的返回值存储在哪里?
它存储在评估堆栈中.然后使用评估堆栈中的值调用下一个方法.在链中调用最后一个方法后,结果将重新设置为本地变量名.
查看Call指令,了解它如何逐步运行:
Method arguments arg1 through argN are pushed onto the stack.
Method arguments arg1 through argN are popped from the stack; the
method call is performed with these arguments and control is
transferred to the method referred to by the method descriptor. When
complete, a return value is generated by the callee method and sent
to the caller.The return value is pushed onto the stack.
因此,在调用方法之前,它的参数被压入堆栈.在你的第一个代码中它是这样的:
>将_employees推入堆栈,Push Func< Employee,bool>到堆栈上
>打电话给哪里
>将结果存储在本地0
>加载本地0(将其推入堆栈),按Func< Employee,string>到堆栈上
>致电OrderByDescending
>将结果存储在本地1中
>加载本地1,推送功能<员工,字符串>到堆栈上
>呼叫选择
>将结果存储在local2中
第二个版本中没有加载本地内容,因为方法调用的返回值已存储在堆栈中.当一个方法被调用时,你的返回值将成为下一个调用的第一个参数,只有作为第二个参数的委托被压入堆栈并调用下一个方法.
我还要提一下,这根本不是LINQ特有的.方法链这样工作,LINQ并不特别.
注意:我已经简化了推送委托步骤,额外的代码用于缓存.在创建新的委托实例编译器之前,委托实例将缓存在编译器生成的类的字段中,以检查它是否为了效率而创建.
内容总结
以上是互联网集市为您收集整理的c# – LINQ序列 – 它们如何在IL中链接?全部内容,希望文章能够帮你解决c# – LINQ序列 – 它们如何在IL中链接?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。