C# 是否列出<;T>;。最后()枚举集合?

C# 是否列出<;T>;。最后()枚举集合?,c#,.net,list,collections,linq-to-objects,C#,.net,List,Collections,Linq To Objects,考虑到已知的集合边界,.Last()是否枚举集合 我之所以问这个问题,是因为声明它是由Enumerable定义的(在这种情况下,它需要枚举集合) 如果它确实枚举了集合,那么我可以简单地通过索引访问最后一个元素(我们知道列表的.Count),但必须这样做似乎很愚蠢……如果它是IEnumerable而不是IList(使用数组或列表,则会使用索引),它确实枚举集合 Enumerable.Last以以下方式实现(ILSpy): publicstatictsource Last(此IEnumerable源

考虑到已知的集合边界,
.Last()
是否枚举集合

我之所以问这个问题,是因为声明它是由
Enumerable
定义的(在这种情况下,它需要枚举集合)


如果它确实枚举了集合,那么我可以简单地通过索引访问最后一个元素(我们知道
列表的
.Count
),但必须这样做似乎很愚蠢……

如果它是
IEnumerable
而不是
IList
(使用数组或列表,则会使用索引),它确实枚举集合

Enumerable.Last
以以下方式实现(ILSpy):

publicstatictsource Last(此IEnumerable源)
{
if(source==null)
{
抛出错误。ArgumentNull(“源”);
}
IList list=源作为IList;
如果(列表!=null)
{
int count=list.count;
如果(计数>0)
{
返回列表[计数-1];
}
}
其他的
{
使用(IEnumerator enumerator=source.GetEnumerator())
{
if(枚举数.MoveNext())
{
t电源电流;
做
{
当前=枚举数。当前;
}
while(枚举数.MoveNext());
回流;
}
}
}
抛出错误。NoElements();
}

如果您知道您有一个
列表
,那么只需快速访问最后一个元素,而不必依赖
last()
中可能未记录的优化。(碰巧,
Last()
检查接收方是否实现了
IList
,并优化了该情况。)@dlev是的,正如我提到的,我知道我可以做到这一点。。。我特别询问的是
的实现。Last
我很确定实现会检查
列表
并尽可能按索引访问最后一个元素。很多LINQ扩展都会检查索引类型作为优化。如果Last()也这么做,我也不会感到惊讶。当然,这是实现定义的,不应该依赖。对,但我要说的是,你不应该依赖行为,因为它没有这样的文档记录(即使它确实执行了优化)。你提供的代码表明,不,它不会导致
列表的枚举。。。但是你的第一行说“是”;-)@MatthewPK它是“是的,如果不是
IList
,它将迭代整个可枚举项”,这有点令人困惑,但却是正确的。@TimSchmelter,那么我很困惑<代码>列表
当然实现了IList
所以。。。。答案不是对我的头衔说“不”吗?我知道这是语义学。。。我只是想知道我是否遗漏了你的答案……@TimSchmelter你的答案完全被理解(并将被接受)。。。我只是觉得这句话令人困惑:)
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];
        }
    }
    else
    {
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            if (enumerator.MoveNext())
            {
                TSource current;
                do
                {
                    current = enumerator.Current;
                }
                while (enumerator.MoveNext());
                return current;
            }
        }
    }
    throw Error.NoElements();
}