1. 程式人生 > >再次理解 C# LINQ

再次理解 C# LINQ

語言整合查詢 (LINQ) 是一系列直接將查詢功能整合到 C# 語言的技術統稱。

查詢表示式(生成表示式)

 1、IEnumerable<T> 查詢編譯為委託。如 source.Where(m=>m.Id>1) 返回一個表示式,這個表示式可以轉為委託。

2、 IQueryable 和 IQueryable<T> 查詢編譯為表示式樹。

儲存查詢結果(計算表示式)

兩個測試幫助理解 什麼是生成表示式什麼是計算表示式

    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