C# 集合被修改为异常。它在引擎盖下是如何工作的?
若在枚举期间修改集合,列表将产生此异常,但它是如何工作的?列表是否在每次启动枚举时都在内部设置一些标志,然后在修改集合的每个方法中检查它?如果您多次枚举同一个列表会怎么样?它如何跟踪其状态 下面是一个基本示例:C# 集合被修改为异常。它在引擎盖下是如何工作的?,c#,C#,若在枚举期间修改集合,列表将产生此异常,但它是如何工作的?列表是否在每次启动枚举时都在内部设置一些标志,然后在修改集合的每个方法中检查它?如果您多次枚举同一个列表会怎么样?它如何跟踪其状态 下面是一个基本示例: using System; using System.Linq; public class Program { public static void Main() { var collection = Enumerable.Range(0, 100).T
using System;
using System.Linq;
public class Program
{
public static void Main()
{
var collection = Enumerable.Range(0, 100).ToList();
foreach(var item in collection)
{
Console.WriteLine(item);
collection.RemoveAt(0); // how does list knows that we are enumerating collection?
}
}
}
我很想用谷歌搜索答案,但快速搜索是没有用的。据我记忆所及,C#不是开源的,所以我无法检查源代码。反射是一种选择,但我宁愿将其保存为最后手段。列表类包含一个名为\u version
的私有字段。它是一个整数,每次添加、删除、排序或反转列表时都会递增
开始枚举列表时,list
生成一个枚举器实例,该实例立即获取\u version
字段的副本,并将其存储在自己的名为version
的成员变量中。每次从枚举器请求项目时,它都会进行检查以确保version==\u version
。如果基础列表已更改,则其版本将更改;当检测到这种情况时,枚举器抛出您看到的异常
请参阅以查看实现。“据我所知,C#不是开源的”一个简单的web搜索将为您解答这个问题,从而避免记住它。下面是一个链接,回答您的问题:(您正在查找
\u version
字段)不确定您需要知道的原因。信息隐藏原理告诉我们,不必知道设计决策是一件好事。您需要知道的是,在列表更改后使用枚举数会导致异常。依赖任何更具体的东西都是不好的做法,因为将来可能会发生变化。@ThomasHilbert这不是一般的枚举行为,而是列表的枚举器(以及其他特定的枚举实现)的行为。@ThomasHilbert知道和依赖是有区别的。你越了解事物的工作原理,你就越能更好地使用它。