for和foreach有什么区别?

24

for循环和foreach循环的主要区别是什么?

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

能否用一个简单的程序来演示?

它们两个看起来都一样。我分不清它们。


3
简短回答:如果迭代顺序很重要,你应该使用for(例如,如果你想向后迭代集合或只想迭代它的每第二个元素),如果迭代顺序不重要,则使用foreach。(顺便说一句,在需要迭代顺序的情况下也可以使用foreach - 在这种情况下,需要重新构造集合。但这会降低程序性能) - Agnius Vasiliauskas
19个回答

26

一个 for 循环是一种结构,它表示“执行这个操作 n 次”。

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


24
for 不是真正的 "n 次",而是 "当满足条件时",这个条件通常是一个简单的计数器检查。对于 foreach,实际上不需要使用 IEnumerable,但确实:从语义上讲,它是一个"依次获取每个项" 的 API。 - Marc Gravell
1
当然,你是正确的 - 但大多数情况下,你给出的更精确的定义,是大多数人倾向于认为do/while循环的方式。 - Dave Bish
1
添加一点,for循环规定了特定的顺序,由循环索引变量表示。foreach不太受顺序限制,因为没有索引变量。这对并行性产生了很大的影响。 - dthorpe

13

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


6
从技术上讲,IEnumerable 接口并不是 foreach 的必要条件,但基本上就是这样;p - Marc Gravell
1
一般来说,任何提供“Current”属性和“MoveNext”方法的接口都足够了,对吧?这应该与Jon Skeet重新实现LINQ或Task时的技术情况相同吧? - Femaref

11

我将尝试以更通用的方式回答:

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更快(特别是在使用链表时)。


在你上面的foreach代码块中,你使用String类而不是string数据类型有什么原因吗?只是出于好奇,但我通常更喜欢使用string数据类型。另外,也许要为for循环添加上下文,它与foreach循环明确分开,因为它仅在满足条件操作时运行,而foreach循环则不会,它遍历整个集合。 - aidangig

5

就foreach而言,大家已经给出了正确的答案,它是一种遍历实现IEnumerable接口的元素的方式。

另一方面,相对于其他答案展示的内容,for更加灵活。实际上,for用于在指定条件为true的情况下执行一组语句的代码块。

来自Microsoft文档:

for (initialization; test; increment)
     statement

初始化 必需。一个表达式。该表达式仅在循环执行之前执行一次。

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

递增 必需。一个表达式。递增表达式在每次通过循环时都会执行。

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

这意味着您可以以许多不同的方式使用它。经典的学校例子是从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);

4

这取决于你要做什么和你需要什么。

如果你正在遍历一个项目集,不关心索引值,则 foreach 更方便,更容易编写且更安全:你无法错误地得到项数。

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

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

有关更多详细信息,请参阅 MSDN:foreachfor


1
抱歉进行了微不足道的编辑 - 这是我唯一能够取消我的意外点赞的方法。 - Matt Caton

4

foreach几乎相当于:

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

为了实现“foreach”兼容模式,需要提供一个类,该类具有一个方法GetEnumerator(),该方法返回一个具有MoveNext()方法、Reset()方法和Current属性的对象。
事实上,您不需要实现IEnumerable或IEnumerator。
一些派生点:
  • foreach不需要知道集合长度,因此允许遍历“流”或一种“元素生成器”。
  • foreach在迭代器上调用虚拟方法(大多数情况下),因此可能比for执行得更差。

4

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 ;
}

3

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

  1. For循环执行一段代码块直到某个表达式返回false,而ForEach循环遍历对象集合中的元素执行代码块。

  2. For循环可以在有或没有对象集合的情况下执行,而ForEach循环只能在有对象集合的情况下执行。

  3. For循环是一个通用的循环结构,可用于多种目的,而foreach仅适用于集合或IEnumerables对象。


1
此外,在“for”循环中,我们可以更新集合,而在“foreach”循环中,一旦执行循环,就无法更改集合。 - Surendra Shrestha

2

for循环会重复执行一个语句或一组语句,直到指定的表达式为false。需要指定循环边界(最小或最大值)。以下是一个简单的for循环代码示例,从0开始,直到5。

我们详细了解foreach。看起来像外部的简单循环实际上是一个复杂的数据结构,称为枚举器:

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

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

但枚举器的缺点是它们需要对序列中的每个元素调用CurrentMoveNext。所有这些方法调用都会累积,特别是在关键任务代码中。

相反,for循环只需对列表中的每个元素调用get_Item。这比foreach循环少了一个方法调用,差异真的很明显。

那么何时应该使用foreach循环,何时应该使用for循环?

以下是需要做的事情:

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


2

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接