gpt4 book ai didi

c# - 为什么这个 foreach 循环不抛出 "collection was modified"异常?

转载 作者:行者123 更新时间:2023-12-02 16:03:08 25 4
gpt4 key购买 nike

我正在使用 .NET Framework 4.0。

神奇之处在于 OrderBy() LINQ 方法中的某处。这里有几个例子供您引用:

var list = new List<int> { 1, 2, 3, 4, 5, 6};
foreach (var item in list)
{
if (item % 2 == 0)
list.Remove(item);
}

这个循环,正如预期的那样,抛出 "System.InvalidOperationException: Collection was modified; enumeration operation may not execute." 异常。

但是,如果我添加对 OrderBy() 的调用:

foreach (var item in list.OrderBy(v => v))
{
if (item % 2 == 0)
list.Remove(item);
}

代码执行得很好,从列表中删除了所有偶数。

起初我假设 OrderBy() 只是枚举源列表并创建它的排序副本。这是有道理的,并解释了为什么循环不抛出异常:我没有枚举我正在修改的相同列表。然而在the documentation (“备注”部分)声明:

This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.

那么这是文档中的错误(可能是不小心复制粘贴了这个 block ?)还是我遗漏了什么?

附言有 this question , 但投票最多 answer假设 OrderBy() 只是枚举列表。我很想知道它是否真实(对某些 .NET 源的引用非常欢迎)。也许副本确实没有创建,但源列表在我修改之前已完全枚举?

最佳答案

我认为这是因为当 OrderBy开始执行它会在 Buffer<T> 中创建列表的副本打电话上课 ToArray ,因此修改原始列表不会引发异常。这是一个 reference to the source code

 internal Buffer(IEnumerable<TElement> source)
{
if (source is IIListProvider<TElement> iterator)
{
TElement[] array = iterator.ToArray();
_items = array;
_count = array.Length;
}
else
{
_items = EnumerableHelpers.ToArray(source, out _count);
}
}

Buffer GetEnumerator 中初始化方法:

public IEnumerator<TElement> GetEnumerator()
{
Buffer<TElement> buffer = new Buffer<TElement>(_source);
if (buffer._count > 0)
{
int[] map = SortedMap(buffer);
for (int i = 0; i < buffer._count; i++)
{
yield return buffer._items[map[i]];
}
}
}

关于c# - 为什么这个 foreach 循环不抛出 "collection was modified"异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70160461/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com