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包装

待续!


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3