【问题标题】:faster way between to ways of iterating through all the elements of a collection in C# [duplicate]在 C# 中遍历集合的所有元素的方法之间的更快方法[重复]
【发布时间】:2013-12-26 16:36:55
【问题描述】:

我使用的语言是 C#。

让我们有一个T类型的对象列表,

List<T> collection = new List<T>{.....};

假设我们要遍历集合中的每个项目。这可以通过多种方式完成。其中,有以下两种:

foreach(var item in collection)
{
   // code goes here
}

foreach(T item in collection)
{
    // code goes here
}

第二种方法比第一种更好吗?为什么?

提前感谢您的回答。

【问题讨论】:

  • exactly the same
  • 在运行时没有var 这样的东西。两者将发出相同的编译代码。
  • 唯一需要注意的是,当您创建foreach 时,如果您做了一些导致编译器对该类型发出强制转换操作的操作。例如,List&lt;object&gt; o;foreach (string i in o) 将添加 IL 调用以尝试将迭代器的当前项转换为字符串。这是对支持旧 .NET 集合的回归。
  • 一种更快的方法可能是使用for 而不是foreach,我已经读到它在某些条件下确实表现更好。
  • 测量并找出答案。 您已经以两种方式编写了代码;现在运行它,看看哪个更快。

标签: c# foreach


【解决方案1】:

两者完全相同。 var 是为了方便起见的语法糖。这对遍历 List 的速度没有影响。

我遵循var 的经验法则是,仅当对象的类型出现在赋值的右侧时才使用它,所以在这种情况下,我更愿意在foreach 让其他工程师更清楚,但这取决于个人选择。如果您将鼠标悬停在 Visual Studio 中的 var 上,它将显示类型(假设它可以推断应该是什么)。

【讨论】:

  • Chris 是正确的,使用 var 绝对不会影响速度 - 两个循环在编译时都会被翻译成相同的字节码。
  • 有时var 不仅是“语法糖”,而且是必须的。例如,当您遍历匿名对象列表时。
  • @haim770 确实,匿名类型是必须的 - 谢谢!
  • @haim770 好吧,你不知道have to,但如果你不这样做,它就是一个巨大的 PITA。
  • @ScottChamberlain,'PITA'?如果你想写一个简单的foreach,就像你以前写的“常规”类型一样,你“必须”。
【解决方案2】:

引用 MSDN:

一个隐式类型的局部变量是强类型的,就像你 自己声明了类型,但是编译器决定了类型。

所以

var i = 10; // implicitly typed
int i = 10; //explicitly typed

完全一样。

现在,为了“更好” - 这在很大程度上取决于您的判断参数。如果是速度,那么for 循环可能比foreach 更好,T[]List&lt;T&gt;according to Patrick Smacchia 更好。要点:

  • List 上的 for 循环比 List 上的 foreach 循环便宜 2 倍多。
  • 在数组上循环比在 List 上循环便宜大约 2 倍。
  • 因此,使用 for 在数组上循环比使用 foreach 在 List 上循环便宜 5 倍(我相信,我们都这样做)。

引用来源:In .NET, which loop runs faster, 'for' or 'foreach'?

参考:http://msdn.microsoft.com/en-us/library/bb383973.aspx

【讨论】:

    【解决方案3】:

    如果您比较 IL 代码,您会发现它们确实 100% 相同。 var 只是语法糖:

    C#代码:

      List<int> collection = new List<int>();
      collection.Add(1);
      collection.Add(2);
      collection.Add(3);
    
      foreach (var myInt in collection)
      {
        Console.WriteLine(myInt);
      }
    
      foreach (var T in collection)
      {
        Console.WriteLine(T);
      }
    

     bool flag;
    
                System.Collections.Generic.List<int> list = new System.Collections.Generic.List<int>();
                list.Add(1);
                list.Add(2);
                list.Add(3);
                System.Collections.Generic.List<int>.Enumerator enumerator = list.GetEnumerator();
                try
                {
                    while (flag)
                    {
                        int i1 = enumerator.get_Current();
                        System.Console.WriteLine(i1);
                        flag = enumerator.MoveNext();
                    }
                }
                finally
                {
                    enumerator.Dispose();
                }
                enumerator = list.GetEnumerator();
                try
                {
                    while (flag)
                    {
                        int i2 = enumerator.get_Current();
                        System.Console.WriteLine(i2);
                        flag = enumerator.MoveNext();
                    }
                }
                finally
                {
                    enumerator.Dispose();
                }
    

    【讨论】:

      【解决方案4】:

      没有更快的方法来遍历同一个集合。

      无论您使用什么,您自己的循环或扩展方法 - 这都是一样的。当你使用 var 时 - 它仍然编译成同样的东西。

      唯一的区别可能是,如果您使用 Dictionary,它在搜索值方面会比 List&lt;T&gt;Collection 更快。字典的设计针对搜索进行了优化

      【讨论】:

        【解决方案5】:

        第一种方式(使用 var)可能更好的可读性。 考虑一下:

        List<User> list = new List<User>();
        var users = list.GroupBy(x => x.Name).OrderBy(x => x.Key);
        foreach (var user in users)
        {
         //blah
        }
        

        foreach (System.Linq.IGrouping<string, User> user in users)
        {
        }
        

        我相信这是首先使用 var 的主要原因。

        【讨论】:

        • 这是“更好的可读性”的一个非常糟糕的例子。考虑到它使用的是完全命名空间的类型 + 它是一个组,用户名是 user。我认为这是使用 var 关键字的理想候选者。
        • @James Ups.. 我的意思是第一种方式。
        • 我必须同意@James 的观点。两个块不相等。和美一样,可读性也在旁观者的眼中;第一块的前三行比第二块更有助于理解。
        • @OnoSendai foreach (var user in users)... 和 foreach (System.Linq.IGrouping user in users) 做同样的事情,你同意吗?对于 linq 结果,我通常不想知道确切的类型,所以我更喜欢使用 var 而不是输入 30 字符长的类型 - 我坚信 99% 的开发人员会有相同的感觉,不是吗?跨度>
        • @Eugene 我的意思是这两个块不等价;第 2 部分的哪一部分暗示订购?作为一名程序员,我很早就学到了“永远不要假设任何事情”。个人偏好与代码可维护性无关,而且由于大量使用匿名输入,您可能会让初级程序员的生活变得非常艰难。
        猜你喜欢
        • 2021-11-18
        • 2014-02-25
        • 2021-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-12
        • 2013-08-16
        • 1970-01-01
        相关资源
        最近更新 更多