C#_深入理解Linq的順延強制

來源:互聯網
上載者:User
    一、Linq簡介

    Linq的查詢三部曲:一、擷取資料來源;二、建立查詢;三、執行查詢。
    二、延遲查詢帶來的好處

    延遲查詢有什麼好處呢。請看下面一段代碼:

 private static void Main()        {            var list = new List<int>();            var rd = new Random();            for (var i = 0; i < 100000000; i++)            {                var num = rd.Next(-10000000, 10000000);                list.Add(num);            }            RecordingTime(list);        }
 private static void RecordingTime(IEnumerable<int> list)        {            var watch = new Stopwatch();            watch.Start(); //開始計時            var nums1 = list.Where(n => n > 0);            var nums2 = new List<int>();            foreach (var i in list)            {                if (i > 0)                {                    nums2.Add(i);                }            }             watch.Stop(); //停止計時            var time = watch.ElapsedMilliseconds;            Console.WriteLine($"耗時:{time}毫秒");        }

    大家可以對比一下num1和num2的運行效率,一億條資料中,使用Linq求集合中的正數耗時僅為2毫秒(可能會有十幾毫秒的誤差);而使用普通方法(遍曆加判斷)耗時卻達到了2秒多。效率提升近2000倍。

    Linq的效率為什麼會這麼快呢。

    這是因為Linq在上面的代碼中僅僅做了兩個工作:1、擷取資料來源,2、建立查詢;而使用普通方法不光做了這兩個工作,它還多做了執行查詢工作,因此Linq在此處運行效率奇高。     三、順延強制會有什麼影響     用代碼說話

var list = new List<int> { 1, 2, 3, 4, 5, 6, 7 };            var enumList = list.Where(x => x > -4);            foreach (var num in enumList)            {                Console.WriteLine(num);            }            Console.WriteLine("■■■■■■■■■■■■");            list.Add(-1);            foreach (var num in enumList)            {                Console.WriteLine(num);            }
    此處我上下遍曆的enumList是同一個集合,儘管我在遍曆完第一次的時候改變了List,正常來講我上下兩次遍曆輸出的內容應該是一致的,然而結果卻不盡然。

    剛剛提到Linq僅僅做了兩部工作:1、擷取資料來源,2、建立查詢。那麼執行查詢是在何時何處被執行的呢。答案就是:當enumList被用到的時候才會去執行,也就是說這段代碼中,var enumList = list.Where(x => x > -4);這行代碼被執行了兩次。第一次執行的時候是第一次遍曆enumList的時候,第二次執行的時候是第二次遍曆enumList的時候(大家可以打斷點觀察一下)。        四、順延強制的原理     繼續上代碼

private static void Main()        {            var list = new List<int> { -1, 1, 2, 3, 4, 5 };            var list1 = Delay(list);            foreach (var num in list1)            {                Console.WriteLine(num);            }            list.Add(-3);            list.Add(7);            Console.WriteLine("■■■■■■■■■■■■");            foreach (var num in list1)            {                Console.WriteLine(num);            }        }
 private static IEnumerable<int> Delay(IEnumerable<int> list)        {                      foreach (var num in list)            {                if (num>0)                {                    yield return num;                }                           }        }
    其實Linq的順延強制原理很簡單,如果你理解yield return,那麼你就會明白這兩者其實原理是一模一樣的。
    可以發現這段代碼跟上面的那段代碼運行模式是一樣的,當你將斷點打在var list1 = Delay(list);時,單步調試是不會進入Delay方法的,僅當你去遍曆list1的時候它才會去執行Delay方法,而且是你用幾次list1,它就會去執行幾次Delay方法。yield return與return不同之處就在於它是“按需供給”,即你什麼時候用它就什麼時候(執行)返回給你值。
    之前說到順延強制可能會影響結果,那麼當我多次使用list1時,Delay這個方法就會多次執行,程式的運行效率是否會非常低呢。看一下我的測試,一萬個整形資料列印七次。     yield return(類比順延強制):
直接列印:     普通列印的已耗用時間甚至更低(因為普通列印是列印所有數字,Delay方法過濾掉負數了)。由此,可以看出:當順延強制的結果被多次調用時,並不會影響運行效率。
    五、哪些Linq查詢操作符是順延強制的     轉到Linq查詢操作符的定義看一下
    當傳回值為IEnumerable<TSource>、IEnumerable<IGrouping<TKey, TSource>>和IOrderedEnumerable<TSource>的時候,Linq為順延強制。實際上上述三個傳回值類型都實現了IEnumerable<T>(公開枚舉數)這個介面,yield return的傳回值就是IEnumerable<T>,所以,當Linq查詢操作符的傳回值為上述三個類型時,查詢為延遲查詢,其他為立即執行。     六、如何避免順延強制     可以看到順延強制既有好處又有一定的影響,當順延強制會對自己的程式產生影響時,如何去避免這個影響呢。很簡單,將傳回值轉換為另外一種類型即可,Linq的查詢操作符中包含了轉換操作的定義:ToArray(轉換為數組)、ToDictionary(轉換為字典)、ToList(轉換為集合),使用這些轉換運算就可以將順延強制轉換為立即執行,也就可以避免順延強制帶來的影響了。
本人的第一篇博文,初學C#不到3個月,寫得不好的地方請在評論區指出,我會及時修正。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.