OfType<>() 和 Where() 扩展中的检查类型之间的区别
本文关键字:区别 检查 类型 之间 Where OfType 扩展 | 更新日期: 2023-09-27 18:21:21
除了可读性之外,以下 linq 查询之间有什么区别,以及我何时以及为什么使用一个查询:
IEnumerable<T> items = listOfItems.Where(d => d is T).Cast<T>();
和
IEnumerable<T> items = listOfItems.OfType<T>();
更新:Dang,很抱歉在尝试简化我的问题时引入了一些错误
我们比较三种方法(注意泛型参数(:
-
IEnumerable<X>
调用listOfItems.Where(t => t is T)
仍将返回刚刚过滤为仅包含类型T
元素IEnumerable<X>
。 -
listOfItems.OfType<T>()
调用IEnumerable<X>
将返回包含可转换为类型T
的元素IEnumerable<T>
。 -
IEnumerable<X>
上调用listOfItems.Cast<T>()
将返回包含转换为类型T
的元素的IEnumerable<T>
,或者在无法转换任何元素时引发异常。
listOfItems.Where(d => d is T).Cast<T>()
基本上做了两次相同的事情 - Where
过滤所有T
但仍保留类型IEnumerable<X>
的元素,然后Cast
再次尝试将它们强制转换为T
但这次返回IEumerable<T>
。
listOfItems.Where(d => d is T)
返回一个IEnumerable<U>
(其中 U 是 listOfItems 中项的类型(,仅包含 T 类型的项。
listOfItems.OfType<T>()
返回一个IEnumerable<T>
。
如果我对你的示例进行一些自由,并在 LINQPad 中将其解决,这就是我得到的:
方法
List<T> GetNumbers<T>(List<T> nums){
return nums.Where(d => d is T).ToList<T>();
}
List<T> GetNumbersOfType<T>(List<T> nums){
return nums.OfType<T>().ToList<T>();
}
伊利诺伊
州GetNumbers:
IL_0000: ldarg.1
IL_0001: ldnull
IL_0002: ldftn 05 00 00 2B
IL_0008: newobj 0A 00 00 0A
IL_000D: call 06 00 00 2B
IL_0012: call 07 00 00 2B
IL_0017: ret
GetNumbersOfType:
IL_0000: ldarg.1
IL_0001: call 08 00 00 2B
IL_0006: call 07 00 00 2B
IL_000B: ret
我不是 IL 专家,但看起来 GetNumbers
方法(使用 Where
语法(每次通过循环创建一个新对象,因此可能比 GetNumbersOfType
方法(使用 OfType
(消耗更多的内存。
本质上,编译代码的编译运行时配置文件没有区别。 OfType<T>
返回一个在内部执行is
测试并yield return
匹配的测试的OfTypeIterator
。