vs2008 使用LINQ來簡化編程的7個技巧(轉)

http://igoro.com/archive/7-tricks-to-simplify-your-programs-with-linq/

LINQ體驗系列文章導航:http://www.cnblogs.com/lyj/articles/1119671.html
有關教材可下載
自從學習LINQ以來,我發現了很多使用LINQ來改善代碼的方式。每一個技巧都讓代碼寫起來更簡單,可讀性更強。
這裏總結了這些技巧。我會介紹如何使用LINQ來:
  • 初始化數組
  • 在一個循環中遍歷多個數組
  • 生成隨機序列
  • 生成字符串
  • 轉換序列或集合
  • 把值轉換爲長度爲1的序列
  • 遍歷序列的所有子集
如果你在LINQ方面有心得也歡迎在評論中一起分享。
1. 初始化數組
通常,我們需要把數組的值初始化爲相同的值或遞增的序列值,或者可能是一個步進不爲1的遞增/遞減序列。有了LINQ,我們可以在數組的初始化器中完成所有工作,不再需要循環!
在如下的示例代碼中,第一行代碼初始化了一個長度爲10的數組,所有元素都是-1,第二行代碼初始化b爲0、1、2到9,第三行代碼初始化c爲100、110、120到190.
    int[] a = Enumerable.Repeat(-1, 10).ToArray();
    int[] b = Enumerable.Range(0, 10).ToArray();
    int[] c = Enumerable.Range(0, 10).Select(i => 100 + 10 * i).ToArray();
    要提醒一下:如果你初始化一個很大的數組,最好不考慮這種優雅的方式而是使用傳統的方式來替代。LINQ的這種解決方案會動態產生數組,因此垃圾數組需要在運行時被回收。也就是說,我總是會在小數組或測試調試代碼的情況下使用這種技巧。
2. 在一個循環中遍歷多個數組
    有個朋友問我一個C#的問題:有沒有辦法在一個循環中遍歷多個集合?他的代碼差不多是這樣:
    foreach (var x in array1) {
        DoSomething(x);
    }
    foreach (var x in array2) {
        DoSomething(x);
    }
    這樣的話,循環主體會很大,而且他也不希望這樣重複的代碼。但是,他又不希望創建一個數組來保存array1和array2的所有元素。
    LINQ提供了一種優雅的解決方案:Concat操作。我們可以使用單個循環來重寫上面的代碼,如下:
    foreach (var x in array1.Concat(array2)) {
        DoSomething(x);
    }
注意,由於LINQ在枚舉器級別進行操作,他不會產生新的數組來保存array1和array2的元素。因此,除了優雅之外,這個方案還很高效。
3. 生成隨機序列
這是一個生成N長度隨機序列的簡單技巧:
    Random rand = new Random();
    var randomSeq = Enumerable.Repeat(0, N).Select(i => rand.Next());
    有了LINQ的延遲特性,序列不會實現進行計算並保存到數組中,而是在迭代randomSeq的時候按需生成隨機數。
4. 生成字符串
    LINQ同樣也是生成各種類型字符串的好工具。對於測試或調試,生成字符串時很有用的。假設我們需要生成一個N長度的字符串,按照“ABCABCABC”的方式。使用LINQ,解決方案非常優雅:
    string str = new string(
        Enumerable.Range(0, N)
        .Select(i => (char)(‘A’ + i % 3))
        .ToArray());
    Petar Petrov給出了另外一種有趣的方式使用LINQ來生成字符串:
    string values = string.Join(string.Empty, Enumerable.Repeat(pattern, N).ToArray());
5. 轉換序列或集合
    在C#或VB中我們不能實現把序列從T類型轉換爲U類型,即使T從U類繼承。因此,即使把List<string>轉換爲List<object>也很難實現。(要解釋爲什麼,請看Bick Byer的帖子)。但是如果要把IEnumerable<T>轉換爲IEnumerable<U>的話,LINQ有一個簡單而有效的解決方案:
    IEnumerable<string> strEnumerable = …;
    IEnumerable<object> objEnumerable = strEnumerable.Cast<object>();
    如果我們需要轉換List<T>爲List<U>,LINQ也提供瞭解決方案,但是它會進行列表的複製:
    List<string> strList = …;
    List<object> objList = new List<object>(strList.Cast<object>());
    Chris Cavanagh建議另外一種解決方式:
    var objList = strList.Cast<object>().ToList();
6. 把值轉換爲長度爲1的序列
    當我們需要把單個值轉化爲一個長度爲1的序列時,會怎麼做?我們可以創建一個長度爲1的數組,但是我還是喜歡LINQ的Repeat操作:
    IEnumerable<int> seq = Enumerable.Repeat(myValue, 1);
7. 遍歷序列的所有子集
    有了LINQ,我們可以如下聲場所有arr數組的子集:
    T[] arr = ...;
    var subsets = from m in Enumerable.Range(0, 1 << arr.Length)
                  select
                      from i in Enumerable.Range(0, arr.Length)
                      where (m & (1 << i)) != 0
                      select arr[i];
    注意,如果子集的個數超過了int,上面的代碼就不能工作。因此,僅當你知道arr的長度不超過30的時候纔去使用這個方式。如果arr長度超過30,你應該不會是想去遍歷所有的子集,因爲可能這會耗費幾分鐘或更長的時間。
評論和總結
    希望這些技巧對你有用,這些示例代碼都使用C#實現,但是你可以很容易得改變爲其它.NET語言。然而,LINQ對於支持擴展方法、lambda表達式和類型推斷的語言更方便,比如C#和VB。這裏的每一段代碼都可行,但是我不能保證什麼,請在使用前仔細檢查。

http://hi.baidu.com/moonnight366/blog/item/a512a5c4659592af8226ac87.html
幾種常用的測試工具:
http://hi.baidu.com/moonnight366/blog/item/4a6b7aa8c3432bb7cb130cca.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章