【问题标题】:Difference between list.First(), list.ElementAt(0) and list[0]?list.First()、list.ElementAt(0) 和 list[0] 的区别?
【发布时间】:2011-05-29 01:41:42
【问题描述】:

根据标题... list.First()、list.ElementAt(0) 和 list[0] 之间有什么真正的区别吗?

【问题讨论】:

    标签: c# list


    【解决方案1】:
    1. .First() 将在源列表不包含任何元素时引发异常。 See the Remarks section。为避免这种情况,请使用FirstOrDefault()

    2. .ElementAt(0) 如果索引大于或等于列表中的元素数,将抛出异常。为避免这种情况,请使用ElementAtOrDefault(0)。如果您使用的是 LINQ To SQL,则无法将其转换为 sql,而 .First() 可以转换为 TOP 1

    3. 如果索引大于或等于列表中元素的数量,索引器也会抛出异常。它不提供OrDefault 选项来避免这种情况,并且不能将其转换为用于 LINQ To SQL 的 sql。编辑:我忘了提到一个简单的显而易见的事情,即如果您的对象是 IEnumerable,则不能使用这样的索引器。如果你的对象是一个实际的 List,那么你就可以了。

    【讨论】:

    • re: point2 - 就我个人而言,我宁愿索引超出范围异常而不是空引用 - 那些 xOrDefault() 方法是邪恶的!
    • @MattDavey 对我来说,OrDefault 方法需要一个空检查是不言自明的。它们不会导致空引用异常,错误的编码会。
    • @ProfK 我没有说它们导致空引用异常。我说我宁愿有一个 IndexOutOfRangeException 而不是一个空引用。这当然是个人喜好,但我认为空引用没有任何用处。
    【解决方案2】:

    也许是一个老问题,但存在性能差异。

    下面的代码:

     var lst = new List<int>();
    
                for (int i = 0; i < 1500; i++)
                {
                    lst.Add(i);
                }
                int temp;
    
    
                Stopwatch sw1 = new Stopwatch();
    
                sw1.Start();
    
                for (int i = 0; i < 100; i++)
                {
                    temp = lst[0];    
                }
    
    
                sw1.Stop();
    
    
    
    
                Stopwatch sw2 = new Stopwatch();
                sw2.Start();
                for (int i = 0; i < 100; i++)
                {
                    temp = lst.First();
                }
    
                sw2.Stop();
    
                Stopwatch sw3 = new Stopwatch();
                sw3.Start();
                for (int i = 0; i < 100; i++)
                {
                    temp = lst.ElementAt(0);
                }
    
                sw3.Stop();
    

    您将获得以下时间(以刻度为单位):

    • lst[0]

      sw1.ElapsedTicks

      253

    • lst.First()

      sw2.ElapsedTicks

      438

    • lst.ElementAt(0)

      sw3.ElapsedTicks

      915

    【讨论】:

      【解决方案3】:

      在“有效”情况下(即,当列表至少有一个元素时),它们与 APshredder 指出的相同。如果没有元素,那么list[0]list.ElementAt(0 将抛出一个ArgumentIndexOutOfRangeException,而list.First() 将抛出一个InvalidOperationException

      【讨论】:

        【解决方案4】:

        在这些选项之间进行选择的另一个考虑因素是 First()ElementAt(0) 都与 any 序列兼容——IEnumerable 的任何实现。 (这可能很有用,因为这意味着您可以用 IEnumerable 的不同实现替换您的变量,而无需更改任何代码。)相比之下,索引器仅适用于直接实现该功能的列表和其他结构。

        相反,使用索引器可能是确保(在编译时)获得优化性能的好方法,因为ElementAt 有合理的机会是 O(n) 而不是 O(1),而索引器是通常被认为很快。

        【讨论】:

          【解决方案5】:

          不,完全没有区别。他们都做同样的事情,返回列表中的第一项。

          编辑:我想我不应该说没有区别。 ElementAt() 和 First() 都有一些它们所做的错误处理,检查空值和超出范围的索引,但它不应该真的很明显。

          【讨论】:

            猜你喜欢
            • 2017-02-28
            • 2010-10-15
            • 1970-01-01
            • 2011-04-27
            • 2018-02-27
            • 2016-01-08
            • 2014-10-09
            • 2011-11-04
            • 1970-01-01
            相关资源
            最近更新 更多