.NET的foreach语句是否保证按照创建顺序迭代集合?

15

我的同事在他写的C#代码中使用了for循环来迭代一个List,并留下了评论:"没有使用ForEach,因为我不确定它是否按顺序迭代。谁知道微软会做什么。" 例如,假设我们有一个像这样构建起来的List:

var someList = new List<string>();

someList.Add("one");
someList.Add("two");
someList.Add("three");

我的同事使用了类似这样的代码:

for (int i = 0; i < someList.Count; i++)    
{
    System.Diagnostics.Debug.WriteLine(someList[i]);
}

用这个替代:

foreach (var item in someList)              
{
    System.Diagnostics.Debug.WriteLine(item);
}

我猜他担心集合中的项可能以不同于它们添加到集合中的顺序出现。我认为他有点多虑,但从技术上讲,文档没有规定集合迭代的顺序。foreach语句是否可能以任何低于最高绑定到最高绑定之外的顺序遍历数组或集合对象?

3个回答

33

您的问题涉及到一个List<T>,它维护顺序。

仅使用foreach并不能保证任何事情。它只是询问所提供的对象的枚举器,这可能会执行任何操作。


测试一下是否可以克服 Skeet 效应。祈祷成功。 - Rex M
4
因为我点了赞,所以你比我多一个。我猜那不是你想说的 "Skeet effect" ;) - Jon Skeet
谢谢。我没有深入研究文档:http://msdn.microsoft.com/en-us/library/aa288257(VS.71).aspx - raven

23

这取决于集合类型:

  • List<T> 保证按照插入顺序排列。(这是基于只使用 Add 方法添加元素的情况。如果在列表中特定位置插入元素,它们将按照您期望的位置返回。)基本上,它的顺序与通过 list[0]list[1]list[2] 等方式获得的顺序相同。
  • Dictionary<TKey, TValue> 没有保证排序。
  • SortedList<TKey, TValue>(以及类似类型)将按键比较顺序排列 - 这是该类型的目的。
  • 数组总是按元素顺序排列。

尽管你说得对,但我仍然认为foreach仅用于遍历集合中的所有对象,并且绝不保证任何顺序。选择foreach将使用集合实现来确定顺序。因此,使用foreach没有保证行为。 - DevinB
2
@devinb 我想这就是 @Jon 所说的意思。 - Rex M
2
好的,foreach保证使用集合的GetEnumerator方法 - 因此,如果您知道集合的迭代器顺序,则可以保证foreach具有相同的顺序。例如,依赖于它按顺序迭代List是完全合理的。 - Jon Skeet
@Rex,我想我表达不够清楚。我的意思是foreach的顺序应该被视为副作用。而for循环有保证的顺序。Jon忽略了这个事实,并暗示应该使用foreach。我认为如果索引顺序很重要,那么for循环更安全。 - DevinB
@both:哈...好吧,现在我看起来很愚蠢。不过我会把我的评论留在这里,以便后人可以看到,这样你们回复的就不是空话了。 - DevinB

4

具体回答这个问题,“foreach”返回的是 .GetEnumerator() 返回的顺序。对于列表,它是你添加的内容的末尾顺序。对于字典,它可能是分配物品的桶的顺序。


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