C#Foreach和for之间的差异(非性能)

C#Foreach和for之间的差异(非性能),c#,visual-studio-2008,foreach,C#,Visual Studio 2008,Foreach,不久前,我读到foreach处理对象的“副本”,因此它可以用于信息检索而不是更新。我不明白,因为完全可以循环遍历类列表并更改其字段。谢谢 您可能已经了解到,在使用foreach对集合进行迭代时不能修改集合,而可以(如果小心的话)使用for循环。例如: using System; using System.Collections.Generic; class Test { static void Main() { var list = new List<in


不久前,我读到foreach处理对象的“副本”,因此它可以用于信息检索而不是更新。我不明白,因为完全可以循环遍历类列表并更改其字段。谢谢

您可能已经了解到,在使用
foreach
对集合进行迭代时不能修改集合,而可以(如果小心的话)使用
for
循环。例如:

using System;
using System.Collections.Generic;

class Test
{
    static void Main()
    {
        var list = new List<int> { 1, 4, 5, 6, 9, 10 };


        /* This version fails with an InvalidOperationException
        foreach (int x in list)
        {
            if (x < 5)
            {
                list.Add(100);
            }
            Console.WriteLine(x);
        }
         */

        // This version is okay
        for (int i = 0; i < list.Count; i++)
        {
            int x = list[i];
            if (x < 5)
            {
                list.Add(100);
            }
            Console.WriteLine(x);            
        }
    }
}
使用系统;
使用System.Collections.Generic;
课堂测试
{
静态void Main()
{
var list=新列表{1,4,5,6,9,10};
/*此版本失败,出现InvalidOperationException
foreach(列表中的int x)
{
if(x<5)
{
增加(100);
}
控制台写入线(x);
}
*/
//这个版本还可以
for(int i=0;i

如果这不是您所指的内容,请提供更多详细信息-在不确切了解内容的情况下,很难解释您所阅读的内容。

您无法修改
foreach
中的元素:

var list = new List<string>();
list.AddRange(new string[] { "A", "B", "C" });

foreach (var i in list)
{
    // compilation error: Cannot assign 'i' because it is a 'foreach iteration variable'
    i = "X";
}
var list=newlist();
AddRange(新字符串[]{“A”、“B”、“C”});
foreach(列表中的变量i)
{
//编译错误:无法分配“i”,因为它是“foreach迭代变量”
i=“X”;
}

尽管在使用
for
时,您访问的是列表中的元素及其索引,而不是迭代器,因此您可以通过这种方式修改集合。

foreach使用迭代器获取序列中的每个元素。序列可以是实现IEnumerable的任何内容。IEnumerable不需要是有限的(序列0 1 2 3 4…1000…)是IEnumerable

for只是一个C#构造,它允许您声明一个循环(用于执行所有类型的操作,而不仅仅是迭代集合)


值得注意的是,集合的.NET中的迭代器实现不支持迭代期间的序列修改

foreach
正在使用
IEnumerable
循环收集。这使得无法修改此集合(删除、添加项),但仍然可以修改其中的对象(如果它们是引用类型)


for
是简单循环与直接访问集合中项目的简单组合。此循环运行时没有任何类型的阻塞。

将其与只读字段进行比较:

private readonly List<int> MyList = new List<int>();
最后,如果正在使用基础集合,则不要求用于实现foreach的枚举数保持有效:

foreach(int x in SomeEnumerable)
{
    if(x != 0)
        SomeEnumerable.Add(0);
}

假设
Add
修改了
SomeEnumerable
,那么上面的可能会起作用,它可能会以一种奇怪而难以理解的方式“起作用”,并且可能会引发异常。此类代码不能保证任何行为,因此,在枚举期间修改集合被认为是不正确的。

Jon,谢谢。是的,我阅读了它,并且理解如果循环通过它,我不能删除例如数组的元素。但我认为我可以修改每个元素的内容,对吗?另一个警告是foreach的实现可能与for()使用的索引器非常不同。对于listview的SelectedItems集合,它在性能方面有很大的不同。@Radusko:是的,您可以修改所引用对象中的数据。。。尽管它是值类型,但您仍然需要处理副本。(希望您不必处理可变值类型。)@Jon Skeet:谢谢。不,这些不是值类型,我指的是类。我只是想确定我是否理解了。@Jon Skeet:但是,如果我循环遍历字符串数组,我将无法更改它。字符串是不可变的,但引用是不可变的,这就是原因?实际上,您可以修改作为引用类型的元素(如果可以修改的话)。您不能替换、添加或删除它们。代码无法工作的原因是字符串是不可变的。一旦创建了字符串,就不能以任何方式修改它。看起来是修改的内容实际上是用一个字符串替换另一个字符串。因此,在上面给出的示例中,您替换了其中一个元素(或删除一个元素并添加一个元素),并且在枚举集合时不允许这样做。
foreach(int x in SomeEnumerable)
{
    if(x != 0)
        SomeEnumerable.Add(0);
}