前段时间我读到了一个关于foreach的文章,说它使用“对象的副本”,因此可以用于信息检索而不是更新。但我并不理解,因为完全可以通过循环遍历类的列表并更改其字段。谢谢!
前段时间我读到了一个关于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);
}
}
}
如果这不是你所指的,请提供更多细节 - 不知道确切内容很难解释你所读的。
在 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";
}
虽然在使用 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>();
现在,在这段代码中,我不能执行MyList = new List<int>()
,因为那会改变MyList
指向的内容,但我可以用MyList.Add(3)
来更改所指向的列表。
同样地,您不能更改foreach
迭代所使用的变量,但可以更改它所引用的内容:
foreach(List<int> lst in MyListOfLists)
{
lst = new List<int>(); // not allowed
lst.Add(3); // allowed
}
最后,用于实现foreach
的枚举器如果底层集合正在使用时不需要保持有效:
foreach(int x in SomeEnumerable)
{
if(x != 0)
SomeEnumerable.Add(0);
}
Add
修改了 SomeEnumerable
,那么上面的代码 可能 能够工作,但是它以一种奇怪和难以理解的方式 可能 "工作" 且 可能 抛出异常。这样的代码不保证任何行为,并且在枚举期间修改集合被认为是不正确的原因。