在特定情况下,调用First
and Where
on a string[]
,调用的方法是 theEnumerable.Where
和Enumerable.First
扩展方法。
Enumerable.Where
做这个:
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
// null checks omitted
if (source is TSource[])
return new WhereArrayIterator<TSource>((TSource[])source, predicate);
//the rest of the method will not execute
}
并且构造函数WhereArrayIterator
只是:
public WhereArrayIterator(TSource[] source, Func<TSource, bool> predicate) {
this.source = source;
this.predicate = predicate;
}
所以这里实际上什么也没做,除了创建一个迭代器。
第First
一种方法,没有谓词这样做:
public static TSource First<TSource>(this IEnumerable<TSource> source) {
//null check
IList<TSource> list = source as IList<TSource>;
if (list != null) {
//this branch is not taken as string[] does not implement IList<string>
if (list.Count > 0) return list[0];
}
else {
//this is actually the WhereArrayIterator from before
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext())
return e.Current;
}
}
throw Error.NoElements();
}
但是,第二个First
这样做
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
//null checks
foreach (TSource element in source) {
if (predicate(element)) return element;
}
throw Error.NoMatch();
}
在数组的情况下,它与直接线性访问一样快。
简而言之,这意味着调用First(predicate)
数组会更快一些,速度不会很大,但仍然可以检测到。这可能不适用于列表,当然也不适用于IQueryable
对象,这是一个完全不同的故事。
然而,这是最糟糕的微优化。除非这样做数百万次,否则不会节省太多秒。即使我现在知道这一点,我仍然会使用更清晰的内容来阅读和理解。