LINQ学习笔记:转换方法
转换方法
主要方法:
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包装
待续!