Linq做了很多聪明的事情,例如Count在a上使用()方法返回Count属性的结果IList.是否有一个很好的来源概述了这种优化?
这将是非常有趣的,因为像以前我知道上面所述,我从来没有使用过Count(),因此经常List<T>只返回一个IEnumerable<T>因为我知道调用者需要经常需要列表的实例计数.
但是请记住,Count()并不真正计算包含在其中的实例,IEnumerable<T>但是从返回的List中返回Count属性的结果,因此不会失去性能,这使我将大量的返回类型从List更改为IEnumerable<T>.
Joh*_*ren 13
试试.NET Reflector.它是浏览类库的一个很好的工具,它有一个强大的反编译器,让你可以像编写代码一样查看源代码.
例如,Count()扩展方法就像这样实现
if (source == null)
{
throw Error.ArgumentNull("source");
}
ICollection<TSource> is2 = source as ICollection<TSource>;
if (is2 != null)
{
return is2.Count;
}
ICollection is3 = source as ICollection;
if (is3 != null)
{
return is3.Count;
}
int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
num++;
}
}
return num;
Run Code Online (Sandbox Code Playgroud)
如果源没有实现集合接口,您将不得不计算得到实际的帐户.以这种方式浏览代码是一种很好的学习方式.
我所知道的当前优化:
CountCount如果序列实现ICollection<T>且未使用谓词,则使用该属性.(在.NET 4 Count中也针对非泛型进行了优化ICollection.)
ElementAt/ ElementAtOrDefault如果序列实现,则通过索引访问IList<T>.
Last/ LastOrDefault如果序列实现IList<T>并且未使用谓词,则通过索引访问.
ToArray/ 如果序列实现,则ToList 使用Count属性更有效地分配内存ICollection<T>.(但他们都没有优化ICollection.)
优化可能存在但不是:
Last/ LastOrDefault在使用谓词的情况下不进行优化.没有理由他们无法优化IList<T>,在列表中向后迭代并通过索引访问每个元素.
SequenceEqual可以优化ICollection<T>和ICollection使用Count属性来确定列表是否具有相同的长度,如果不是,则提前爆发.
Skip可以优化IList<T>,通过索引访问元素并直接从索引n开始,而不是迭代和丢弃前n个元素.
ToArray/ ToList还可以优化ICollection,使用Count属性更有效地分配内存.
ToDictionary可以优化,ICollection<T>并ICollection使用Count属性更有效地分配内存.