轉換方法
主要方法:
OfType: 將IEnumerable轉換為IEnumerable, 同時丟棄那些非目標類型的錯誤元素
Cast: 將IEnumerable轉換位IEnumerable, 如果源序列包含有非轉換目標類型的元素將會拋出異常
ToArray: 將IEnumerable轉換為T[]
ToList: 將IEnumerable轉換為List
ToDictionary: 將IEnumerable轉換為Dictionary</TKEY,>
ToLookup: 將IEnumerable轉換為ILookup</TKEY,>
AsEnumerable: 向下轉換為IEnumerable
AsQueryable: 轉換為IQueryable
OfType與Cast
OfType和Cast接受一個非泛型的IEnumerable集合並最終返回一個泛型IEnumerable序列, 因而可以做進一步查詢操作:
1: ArrayList classicList = new ArrayList();
2:
3: lassicList.AddRange(new int[] { 3, 4,5 } );
4:
5: Enumerable<int> sequence1 =classicList.Cast<int>();
OfType與Cast的不同之處在於其處理輸入序列中的不兼容元素上面, Cast拋出異常, OfType則是忽略這些不兼容的元素, 繼續我們之前的例子:
1: DateTime offender = DateTime.Now;
2:
3: lassicList.Add (offender);
4:
5: Enumerable<int> sequence2 = classicList
6:
7: OfType<int>(); // 忽略offender
8:
9: Enumerable<int> sequence3 = classicList
10:
11: Cast<int>(); // 拋出異常
元素類型的兼容性實際上就是使用C#的is操作符, 我們可以查看一下OfType的內部實現:
1: public static IEnumerable OfType
2:
3: (IEnumerable source)
4:
5: {
6:
7: foreach (object element in source)
8:
9: if (element is TSource)
10:
11: yield return (TSource)element;
12:
13: }
Cast也是一樣的實現, 唯一的不同就是它省掉了兼容性檢查:
1: public static IEnumerable Cast
2:
3: (IEnumerable source)
4:
5: {
6:
7: foreach (object element in source)
8:
9: yield return(TSource)element;
10:
11: }
其結果是你不能使用Cast將元素從一個值類型轉換為另外一個值類型(相反, 你可以使用一個select操作). 換句話說, Cast並不像C#當中的cast操作符那麼靈活, cast允許類似如下的靜態類型之間的轉換:
1: int i = 3;
2:
3: long l = i; // 靜態轉換 int->long
4:
5: int i2 = (int) l; // 靜態轉換 long->int
我們可以通過使用OfType或者Cast將一個ints序列轉換為longs序列來演示靜態轉換問題:
1: int[] integers = { 1, 2, 3 };
2:
3: IEnumerable<long> test1 =integers.OfType<long>();
4:
5: IEnumerable<long> test2 =integers.Cast<long>();
枚舉test1最終的到0個元素, 而枚舉test2則得到一個異常, 上面提到的OfType和Cast的各自內部實現已經很清楚的解釋了為什麼會得到這樣的結果. 不過就像我們之前建議的, 可以使用Select來實現靜態類型轉換的目的:
1: IEnumerable<long> castLong = integers.Select (s => (long) s);
OfType和Cast對過濾一個泛型輸入序列的向下類型元素是非常有用的. 例如如果你有一個輸入序列類型是IEnumerable, OfType將只會返回apple類型的元素. 這一點尤其在LINQ to XML當中更加有用.
ToArray, ToList, ToDictionary, ToLookup
ToArray和ToList將一個結果集轉成一個數組或者泛型列表. 這些操作符會使輸入序列立即執行枚舉操作(除非是在間接的子查詢或者表達式樹上)
ToDictionary和ToLookup接受如下的參數:
輸入序列: IEnumerable
鍵選擇器(key selector): TSource => TKey
元素選擇器(可選): TSource => TElement
Comparer(可選): IEqualityComparer
ToDictionary同樣也會引起一個立即執行將結果寫入一個泛型Dictionary. keySelector表達式必須評估輸入序列每個元素的唯一性, 否則將會得到一個異常. 相反, ToLookup允許多個元素擁有相同的鍵.
AsEnumerable與AsQueryable
AsEnumerable將一個序列向上轉換為一個IEnumerable, 強制將Enumerable類下面的查詢操作符綁定到後續的子查詢當中.
AsQueryable將一個序列向下轉換為一個IQueryable, 它生成了一個本地查詢的IQueryable包裝
待續!