在IList上调用.Last()会迭代整个列表吗?

Sco*_*ock 8 c#

.Last()扩展方法是否考虑了它是否被调用IList?我只是想知道这些之间是否存在显着的性能差异:

IList<int> numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

int lastNumber1 = numbers.Last();
int lastNumber2 = numbers[numbers.Count-1];
Run Code Online (Sandbox Code Playgroud)

Intuition告诉我第一个选择是O(n),但第二个是O(1).是否.Last()"聪明"足以尝试将其投射到IList

Oha*_*der 19

可能不是,因为它可以做到 list[list.count-1]

反射器验证:

public static TSource Last<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    IList<TSource> list = source as IList<TSource>;
    if (list != null)
    {
        int count = list.Count;
        if (count > 0)
        {
            return list[count - 1];
        }
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.我真正学到的是,在这之后我没有安装.NET Reflector.:) (2认同)

Jon*_*eet 6

这是一个未记录的优化,但无谓的重载Enumerable.Last确实会直接跳到最后.

请注意,谓词的重载不仅仅是从最后开始,正如您预期的那样向后工作 - 它从一开始就向前发展.我相信这是为了避免在谓词可能引发异常(或引起其他副作用)时出现不一致.

见我的博客张贴有关实施第一个/最后/单等获取更多信息-和不一致性这单/的SingleOrDefault的重载之间.