1. 程式人生 > >【轉】編寫高質量代碼改善C#程序的157個建議——建議31:在LINQ查詢中避免不必要的叠代

【轉】編寫高質量代碼改善C#程序的157個建議——建議31:在LINQ查詢中避免不必要的叠代

public line linq查詢 接收 string 第一個元素 style 屬性 但是

建議31:在LINQ查詢中避免不必要的叠代

無論是SQL查詢還是LINQ查詢,搜索到結果立刻返回總比搜索完所有的結果再將結果返回的效率要高。

示例代碼:

    class MyList : IEnumerable<Person>
    {
        //為了演示需要,模擬了一個元素集合
        List<Person> list = new List<Person>()
            {
                new Person(){ Name = "Mike", Age = 20 },
                
new Person(){ Name = "Mike", Age = 30 }, new Person(){ Name = "Rose", Age = 25 }, new Person(){ Name = "Steve", Age = 30 }, new Person(){ Name = "Jessica", Age = 20 } }; /// <summary> /// 叠代次數屬性 /// </summary> public
int IteratedNum { get; set; } public Person this[int i] { get { return list[i]; } set { this.list[i] = value; } } #region IEnumerable<Person> 成員 public IEnumerator<Person> GetEnumerator() { foreach (var
item in list) { //每遍歷一個元素就加1 IteratedNum++; yield return item; } } #endregion #region IEnumerable 成員 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion } class Person { public string Name { get; set; } public int Age { get; set; } }

針對上述集合,返回年齡等於20的第一個元素。下面有兩個查詢模式,我們來考慮哪一個效率更高。

//第一種
var temp = (from c in list where c.Age == 20 select c).ToList();
//第二種
var temp2 = (from c in list where c.Age >= 20 select c).First();

通常我們會認為第一種的效率會更高一些,因為它似乎返回的就是等於20的那兩個元素,而第二種模式則需要查詢所有大於等於20的元素。實際上並不是這樣的。看下面測試代碼:

            MyList list = new MyList();
            var temp = (from c in list where c.Age == 20 select c).ToList();
            Console.WriteLine(list.IteratedNum.ToString());
            list.IteratedNum = 0;
            var temp2 = (from c in list where c.Age >= 20 select c).First();
            Console.WriteLine(list.IteratedNum.ToString());

輸出:

5

1

註意:第二次查詢僅僅叠代1次,因為20正好在List的首位。First方法實際完成的工作是:搜索到滿足條件的第一個元素,就從集合返回。如果一個集合包含了很多元素,那麽這種查詢會為我們帶來可觀的時間效率。

與First方法類似的還有Take方法,Take方法接收一個整型參數,然後我們返回該參數指定的個數。與First一樣,它在滿足條件後,會從當前的叠代過程中直接返回,而不是等待整個叠代過程完畢再返回。如果一個集合包含了很多的元素,那麽這種查詢會為我們帶來可觀的時間效率。

註意下面的例子:

            MyList list = new MyList();
            var temp = (from c in list select c).Take(2).ToList();
            Console.WriteLine(list.IteratedNum.ToString());
            list.IteratedNum = 0;
            var temp2 = (from c in list where c.Name == "Mike" select c).ToList();
            Console.WriteLine(list.IteratedNum.ToString());

輸出為:

2

5

雖然LINQ查詢的最後的結果都是返回兩個元素“Mike”對象,但是,實際上,使用Take方法僅僅為我們叠代了2次,而使用where查詢方式帶來的卻是整個集合的叠代。

在實際編碼過程中,要充分運用First和Take等方法,這樣才能為我們的應用帶來高效性,而不會讓時間浪費在一些無效的叠代中。

轉自:《編寫高質量代碼改善C#程序的157個建議》陸敏技

【轉】編寫高質量代碼改善C#程序的157個建議——建議31:在LINQ查詢中避免不必要的叠代