我有两个版本的LINQ选择器,它对非泛型类型进行一些过滤并返回泛型枚举。考虑到我们将使用相同的参数source
来完全枚举这两个参数,我想知道哪种版本会更有效:
public static IEnumerable<ICollection<TData>> OfType1<TData>(this IEnumerable<ICollection> source) =>
source
.Select(c => c as ICollection<TData>)
.Where(c => !(c is null));
public static IEnumerable<ICollection<TData>> OfType2<TData>(this IEnumerable<ICollection> source) =>
source
.Where(c => c is ICollection<TData>)
.Select(c => c as ICollection<TData>);
我认为这全都归结为is
和as
之间的差异,因为在OfType2
中,我们首先过滤(而不是最后过滤),因此可以减少第二个运算符的数量。在第一种情况下,我们需要对可枚举中的所有元素执行两项操作。
那么,在这里实际效果最好的是什么? is
和as
到底有什么不同? (欢迎链接到源代码!)
答案 0 :(得分:6)
由于实现可能会发生变化,因此您确实需要自己进行测试。
但是,您当前的方法有点浪费。 OfType
的性能更高,更直接,分配更少。
从实现中可以看到,它只是使用is
和yield
,这仍然是扩展方法的精神
public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source) {
if (source == null) throw Error.ArgumentNull("source");
return OfTypeIterator<TResult>(source);
}
static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source) {
foreach (object obj in source) {
if (obj is TResult) yield return (TResult)obj;
}
}
其他资源
Enumerable.OfType(IEnumerable) Method
根据指定的类型过滤IEnumerable的元素。