语言集成查询 (LINQ) 是一系列直接将查询功能集成到 C# 语言的技术统称。
查询表达式(生成表达式)
1、IEnumerable<T> 查询编译为委托。如 source.Where(m=>m.Id>1) 返回一个表达式,这个表达式可以转为委托。
2、 IQueryable 和 IQueryable<T> 查询编译为表达式树。
存储查询结果(计算表达式)
- foreach、序列化、求值 或其他访问数据项的行为
两个测试帮助理解 什么是生成表达式什么是计算表达式
public static class ListTest { public static List<T1> Source { get; set; } = new List<T1> { new T1{ Id=1, Name="1" }, new T1{ Id=2, Name="2" }, new T1{ Id=3, Name="3" }, new T1{ Id=4, Name="4" }, new T1{ Id=5, Name="5" }, new T1{ Id=6, Name="6" }, new T1{ Id=7, Name="7" }, new T1{ Id=8, Name="8" }, new T1{ Id=9, Name="9" }, }; public static void Test() { //注意循环性能 foreach (T1 item in Source) { if (item.Id <= 1) { continue; } //do something } /** // loop start (head: IL_002c) IL_000f: ldloca.s 0 IL_0011: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class IListTest.T1>::get_Current() IL_0016: stloc.1 IL_0017: nop IL_0018: ldloc.1 IL_0019: callvirt instance int32 IListTest.T1::get_Id() IL_001e: ldc.i4.1 IL_001f: cgt IL_0021: ldc.i4.0 IL_0022: ceq IL_0024: stloc.2 IL_0025: ldloc.2 IL_0026: brfalse.s IL_002b IL_0028: nop IL_0029: br.s IL_002c IL_002b: nop IL_002c: ldloca.s 0 IL_002e: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class IListTest.T1>::MoveNext() IL_0033: brtrue.s IL_000f // end loop */ foreach (T1 item in Source.Where(m => { return m.Id > 1; })) { //do something } /* // loop start (head: IL_0082) IL_0078: ldloc.3 IL_0079: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<class IListTest.T1>::get_Current() IL_007e: stloc.s 4 IL_0080: nop IL_0081: nop IL_0082: ldloc.3 IL_0083: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() IL_0088: brtrue.s IL_0078 // end loop */ } }
private static string tag; private static void Main(string[] args) { tag = "s"; //IEnumerable<T1> s = Init();//不同实例 List<T1> s = Init().ToList();//同实例 tag = "s2"; IEnumerable<T1> s2 = s.ToList(); if (ReferenceEquals(s.First(m => m.Id == 0), s2.First(m => m.Id == 0))) { System.Console.WriteLine("同实例"); } else { System.Console.WriteLine("不同实例"); } System.Console.ReadLine(); } private static IEnumerable<T1> Init() { for (int i = 0 ; i < 100 ; i++) { System.Console.WriteLine(tag); yield return new T1 { Id = i, Name = "name_" + i }; } }
注意每次计算表达式时都会去生成新的实例,某些情况下不知晓会非常危险。
参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/linq/index
https://docs.microsoft.com/zh-cn/dotnet/csharp/expression-trees