【问题标题】:What is the difference between for and foreach?for 和 foreach 有什么区别?
【发布时间】:2012-06-11 09:01:36
【问题描述】:

forforeach 循环之间的主要区别是什么?

在哪些情况下我们可以使用for 而不是foreach,反之亦然。

可以用一个简单的程序来展示吗?

在我看来,两者都一样。我无法区分它们。

【问题讨论】:

  • Short answer: 如果迭代顺序很重要 - 你应该使用 for (例如,如果你想迭代集合 backwards 或者只是它的每个第二个元素),如果迭代顺序不重要 - 使用foreach。 (顺便说一句,在迭代顺序很重要的情况下也可以使用foreach - 在这种情况下,您需要重新构建集合。但这会降低程序性能)

标签: c# for-loop foreach


【解决方案1】:

for 循环是一个结构,上面写着“执行此操作n.次”。

foreach 循环是一个结构,它表示“针对此 IEnumerable 中的 每个 值/对象执行此操作”

【讨论】:

  • for 并不是真正的“n.次”,而是“在满足此条件时”,这通常是一个简单的计数器检查。你实际上并不需要 IEnumerable 来代替 foreach,但实际上:它在语义上是一个“依次获取每个项目”的 API。
  • 当然你是对的 - 但在大多数情况下,你给出的定义越准确,就是大多数人对 do/while 循环的看法。
  • 添加 for 循环指示特定的顺序,用循环索引变量表示。 Foreach 较少受序列约束,因为没有索引变量。对并行性有很大影响。
【解决方案2】:

如果您要迭代的对象实现了IEnumerable 接口,您可以使用foreach。如果只能通过索引访问对象,则需要使用for

【讨论】:

  • 技术上IEnumerable 接口不是foreach 的先决条件,但差不多;p
  • 一般来说,任何提供Current 属性和MoveNext 方法的接口就足够了,对吧?应该与 Jon Skeet 重新实现 LINQ 或 Task 的技术环境相同吗?
【解决方案3】:

我将尝试以更一般的方式回答这个问题:

foreach 用于以预定义的方式迭代给定集合或列表(任何实现IEnumerable)的每个元素。您无法影响确切的顺序(除了跳过条目或取消整个循环),因为这是由容器决定的。

foreach (String line in document) { // iterate through all elements of "document" as String objects
    Console.Write(line); // print the line
}

for 只是另一种编写循环的方法,该循环在进入循环之前和每次迭代之后执行一次代码。它通常用于循环代码给定次数。与foreach 相反,您可以影响当前位置。

for (int i = 0, j = 0; i < 100 && j < 10; ++i) { // set i and j to 0, then loop as long as i is less than 100 or j is less than 10 and increase i after each iteration
    if (i % 8 == 0) { // skip all numbers that can be divided by 8 and count them in j
        ++j
        continue;
    }
    Console.Write(i);
}
Console.Write(j);

如果可能且适用,请始终使用foreach 而不是for(假设有一些数组索引)。根据内部数据组织,foreach 可能比使用带有索引的for 快很多(尤其是在使用链表时)。

【讨论】:

    【解决方案4】:

    每个人都给了你关于 foreach 的正确答案,即它是一种循环遍历实现 IEnumerable 的元素的方法。

    另一方面, for 比其他答案中显示的灵活得多。实际上,for 用于在指定条件为真时执行一个语句块。

    来自微软文档:

    for (initialization; test; increment)
         statement
    

    初始化 必需的。一种表达。这个表达式只执行一次,在循环执行之前。

    测试 必需的。一个布尔表达式。如果 test 为真,则执行语句。如果测试为假,则终止循环。

    增量 必需的。一种表达。每次循环结束时都会执行增量表达式。

    声明 可选的。如果测试为真,则要执行的语句。可以是复合语句。

    这意味着您可以以多种不同的方式使用它。经典的学校例子是1到10的数字之和:

    int sum = 0;
    for (int i = 0; i <= 10; i++)
        sum = sum + i;
    

    但你也可以用它来对数组中的数字求和:

    int[] anArr = new int[] { 1, 1, 2, 3, 5, 8, 13, 21 };
    int sum = 0;
    for (int i = 0; i < anArr.Length; i++)
        sum = sum + anArr[i];
    

    (这也可以通过 foreach 完成):

    int[] anArr = new int[] { 1, 1, 2, 3, 5, 8, 13, 21 };
    int sum = 0;
    foreach (int anInt in anArr)
        sum = sum + anInt;
    

    但你可以将它用于1到10的偶数之和:

    int sum = 0;
    for (int i = 0; i <= 10; i = i + 2)
        sum = sum + i;
    

    你甚至可以发明一些像这样的疯狂的东西:

    int i = 65;
    for (string s = string.Empty; s != "ABC"; s = s + Convert.ToChar(i++).ToString()) ;
        Console.WriteLine(s);
    

    【讨论】:

      【解决方案5】:

      for循环:

       1) need to specify the loop bounds( minimum or maximum).
      
        2) executes a statement or a block of statements repeatedly 
          until a specified expression evaluates to false.
      

      Ex1:-

      int K = 0;
      
      for (int x = 1; x <= 9; x++){
              k = k + x ;
      }
      

      foreach 语句:

      1)do not need to specify the loop bounds minimum or maximum.
      
      2)repeats a group of embedded statements for 
           a)each element in an array 
        or b) an object collection.       
      

      Ex2:-

      int k = 0;
      
      int[] tempArr = new int[] { 0, 2, 3, 8, 17 };
      
      foreach (int i in tempArr){
          k = k + i ;
      }
      

      【讨论】:

        【解决方案6】:

        foreach 几乎等同于:

        var enumerator = list.GetEnumerator();
        var element;
        while(enumerator.MoveNext()){
          element = enumerator.Current;
        }
        

        并且为了实现“foreach”兼容模式,这需要提供一个具有 GetEnumerator() 方法的类,该方法返回具有 MoveNext() 的对象strong> 方法、Reset() 方法和 Current 属性。

        确实,您不需要实现 IEnumerable 和 IEnumerator。

        一些派生点:

        • foreach 不需要知道集合长度,因此允许遍历“流”或某种“元素生产者”。
        • foreach 在迭代器上调用虚方法(大部分时间),因此性能不如for

        【讨论】:

          【解决方案7】:

          这取决于你在做什么,以及你需要什么。

          如果您正在遍历项目集合,并且不关心索引值,那么 foreach 更方便、更容易编写且更安全:您不会弄错项目数。

          例如,如果您需要处理集合中的每隔一个项目,或者以相反的顺序处理它们,那么 for 循环是唯一实用的方法。

          最大的区别在于,foreach 循环依次处理集合中每个元素的实例,而 for 循环可以处理任何数据,并且不仅限于集合元素。这意味着 for 循环可以修改集合 - 这是非法的,并且会在 foreach 循环中导致错误

          更多详情,请参阅 MSDN:foreachfor

          【讨论】:

          • 对微不足道的编辑表示歉意 - 这是我可以删除我不小心投反对票的唯一方法
          【解决方案8】:

          C#中 For 和 For Each 循环的区别

          1. For 循环执行一段代码,直到表达式返回 false,而 ForEach 循环通过对象集合中的项目执行一段代码。

          2. For 循环可以执行对象集合,也可以不执行任何对象集合,而 ForEach 循环只能执行对象集合。

          3. for 循环是一种普通的循环结构,可用于多种用途,其中 foreach 仅适用于 Collections 或 IEnumerables 对象。

          【讨论】:

          • 此外,在“for”循环中我们可以更新集合,而在“foreach”循环中,一旦执行循环,我们就无法更改集合。
          【解决方案9】:

          如果您有一个数组或其他 IEnumerable 数据集合,则 foreach 很有用。但 for 可用于访问数组中可以通过索引访问的元素。

          【讨论】:

            【解决方案10】:

            当您提前知道或确定您希望循环运行多少次时,for 循环非常有用。例如,如果您需要为一周中的每一天执行一个流程,您就知道需要 7 个循环。

            foreach 循环是指您想要对集合或数组的所有部分重复一个过程,但具体循环运行多少次并不重要。例如,您正在为用户格式化最喜欢的书籍列表。每个用户可能拥有不同数量的书籍,或者没有书籍,我们并不关心它有多少,我们只是希望循环对所有书籍起作用。

            【讨论】:

              【解决方案11】:

              for 循环重复执行一个语句或语句块,直到指定表达式的计算结果为 false。

              需要指定循环边界(最小或最大)。下面是一个从 0 到

              我们详细了解 foreach。外表看起来很简单的循环,其实是一个复杂的数据结构,叫做枚举器:

              枚举器是具有 Current 属性、MoveNext 方法和Reset 方法的数据结构。 Current 属性保存当前元素的值,每次调用 MoveNext 都会将枚举数推进到序列中的下一项。

              枚举器很棒,因为它们可以处理任何迭代数据结构。事实上,它们非常强大,以至于所有的 LINQ 都建立在枚举器之上。

              但枚举器的缺点是它们需要为序列中的每个元素调用 CurrentMoveNext。所有这些方法调用加起来,尤其是在关键任务代码中。

              相反,for 循环只需为列表中的每个元素调用 get_Item。那是比 foreach 循环少一个方法调用,差异确实显示出来了。

              那么什么时候应该使用foreach-loop,什么时候应该使用for-loop?

              您需要执行以下操作:

              使用 LINQ 时,请使用 foreach
              当您处理非常大的计算值序列时,请使用 foreach
              如果性能不是问题,请使用 foreach
              但如果您想获得最佳性能,请改用 for 循环

              【讨论】:

                【解决方案12】:

                我们通过它的工作理解c#中for和foreach循环的主要区别:

                for 循环:

                1. for 循环的变量始终只能是整数。
                2. For 循环重复执行语句或语句块,直到指定表达式的计算结果为 false。
                3. 在 for 循环中,我们必须指定循环的边界(最大值或最小值)。-------->我们可以说这是 for 循环的限制。

                foreach 循环:

                1. 在foreach循环的情况下,循环的变量while与数组下的值的类型相同。

                2. Foreach 语句为数组或对象集合中的每个元素重复一组嵌入语句。

                3. 在 foreach 循环中,您不需要指定循环边界的最小值或最大值。---> 这里我们可以说这就是for each循环的优点。

                【讨论】:

                  【解决方案13】:

                  就性能而言,我更喜欢 FOR 循环。当您处理更多项目时,FOREACH 会有点慢。

                  如果您对实例执行更多业务逻辑,则 FOREACH 执行速度会更快。

                  演示: 我创建了一个包含 10000000 个实例的列表,并使用 FOR 和 FOREACH 进行循环。

                  循环所用时间:

                  • FOREACH -> 53.852ms
                  • FOR -> 28.9232ms

                  下面是示例代码。

                  class Program
                  {
                  
                      static void Main(string[] args)
                      {
                          List<TestClass> lst = new List<TestClass>();
                          for (int i = 1; i <= 10000000; i++)
                          {
                              TestClass obj = new TestClass() {
                                  ID = i,
                                  Name = "Name" + i.ToString()
                              };
                              lst.Add(obj);
                          }
                  
                          DateTime start = DateTime.Now;
                          foreach (var obj in lst)
                          {
                              //obj.ID = obj.ID + 1;
                              //obj.Name = obj.Name + "1";
                          }
                          DateTime end = DateTime.Now;
                          var first = end.Subtract(start).TotalMilliseconds;
                  
                          start = DateTime.Now;
                          for (int j = 0; j<lst.Count;j++)
                          {
                              //lst[j].ID = lst[j].ID + 1;
                              //lst[j].Name = lst[j].Name + "1";
                          }
                          end = DateTime.Now;
                          var second = end.Subtract(start).TotalMilliseconds;
                      }
                  }
                  
                  public class TestClass
                  {
                      public long ID { get; set; }
                      public string Name { get; set; }
                  }
                  

                  如果我取消注释循环内的代码: 然后,循环所用的时间:

                  • FOREACH -> 2564.1405ms
                  • FOR -> 2753.0017ms

                  结论
                  如果你对实例做更多的业务逻辑,那么推荐使用 FOREACH。 如果你没有对实例做太多逻辑,那么推荐使用 FOR。

                  【讨论】:

                  • 欢迎来到 SO,我认为如果您可以提供一些测试结果来显示它们之间存在多少显着差异,这是值得的。
                  • @SaeedZhiany 由于内容大小,我编辑了我的帖子。我通过示例添加了性能细节。
                  【解决方案14】:

                  很多答案已经有了,我只需要找出一个不存在的差异。

                  for 循环是故障安全的,而 foreach 循环是故障快速的。

                  如果在对象中同时完成迭代和修改,则快速失败迭代抛出 ConcurrentModificationException

                  但是,即使迭代进入无限循环,故障安全迭代也可以确保操作不会失败。

                  public class ConcurrentModification {
                      public static void main(String[] args) {
                          List<String> str = new ArrayList<>();
                  
                          for(int i=0; i<1000; i++){
                              str.add(String.valueOf(i));
                          }
                  
                          /**
                           * this for loop is fail-safe. It goes into infinite loop but does not fail. 
                           */
                          for(int i=0; i<str.size(); i++){
                              System.out.println(str.get(i));
                              str.add(i+ "  " + "10");
                          }
                  
                          /**
                           * throws ConcurrentModificationexception 
                          for(String st: str){
                              System.out.println(st);
                              str.add("10");
                          }
                          */
                  
                          /* throws ConcurrentModificationException 
                           Iterator<String> itr = str.iterator();
                          while(itr.hasNext()) {
                              System.out.println(itr.next());
                              str.add("10");
                          }*/
                      }
                  } 
                  

                  希望这有助于从不同的角度理解 for 和 foreach 循环之间的区别。

                  如果有人感兴趣,我找到了good blog 来了解故障安全和快速故障之间的区别:

                  【讨论】:

                  • 简单的while循环迭代也是故障安全的。
                  【解决方案15】:

                  for 和 foreach 的简单区别

                    for loop is working with values.it must have condition then increment and intialization also.you have to knowledge about 'how many times loop repeated'.
                  
                   foreach is working with objects and enumaretors. no need to knowledge how many times loop repeated.
                  

                  【讨论】:

                    【解决方案16】:

                    您可以将 foreach 用于一个简单的数组,例如

                    int[] test = { 0, 1, 2, 3, ...};
                    

                    当你有一个二维数组时,你可以使用 for

                    int[][] test = {{1,2,3,4},
                                    {5,2,6,5,8}};
                    

                    【讨论】:

                    • 您可以同时使用for 和/或foreach
                    【解决方案17】:

                    foreach 语法快速简单。 for 语法稍微复杂一些,但也更灵活。

                    foreach 在迭代集合中的所有项目时很有用。 for 在迭代整个项目或项目子集时很有用。

                    提供每个集合项的foreach迭代变量是只读的,因此我们不能在迭代时修改这些项。使用 for 语法,我们可以根据需要修改项目。

                    底线 - 使用 foreach 快速迭代集合中的所有项目。使用 for 迭代集合中项目的子集或在迭代时修改项目。

                    【讨论】:

                      【解决方案18】:

                      foreach 语句为实现 System.Collections.IEnumerable 或 System.Collections.Generic.IEnumerable 接口的数组或对象集合中的每个元素重复一组嵌入语句。 foreach 语句用于遍历集合以获取您想要的信息,但不能用于从源集合中添加或删除项目以避免不可预知的副作用。如果您需要在源集合中添加或删除项目,请使用 for 循环。

                      【讨论】:

                        【解决方案19】:

                        foreach 相关的一件重要事情是,foreach 迭代变量不能在循环体中更新(或分配新值)。

                        例如:

                        List<string> myStrlist = new List<string>() { "Sachin", "Ganguly", "Dravid" };
                                      foreach(string item in myStrlist)
                        
                                      {
                        
                                          item += " cricket"; // ***Not Possible*** 
                        
                                      }
                        
                        

                        【讨论】:

                        • 其实你错了。您的代码结果将是 { "Sachin cricket", "Ganguly cricket", "Dravid cricket" } 您不能做的是添加/删除列表中的项目。在循环中调用myStrlist.Add("Another"); 将导致异常。
                        猜你喜欢
                        • 2011-01-17
                        • 2019-10-01
                        • 1970-01-01
                        • 2015-05-19
                        • 2016-04-04
                        • 2014-06-06
                        • 2016-06-11
                        相关资源
                        最近更新 更多