在这个问题Foreach loop for disposing controls skipping iterations之后,我对于允许在更改的集合上进行迭代感到困惑:
比如,以下代码:
List<Control> items = new List<Control>
{
new TextBox {Text = "A", Top = 10},
new TextBox {Text = "B", Top = 20},
new TextBox {Text = "C", Top = 30},
new TextBox {Text = "D", Top = 40},
};
foreach (var item in items)
{
items.Remove(item);
}
抛出异常
InvalidOperationException: 集合已被修改;枚举操作无法执行。
但在 .Net 表单中,您可以这样做:
this.Controls.Add(new TextBox {Text = "A", Top = 10});
this.Controls.Add(new TextBox {Text = "B", Top = 30});
this.Controls.Add(new TextBox {Text = "C", Top = 50});
this.Controls.Add(new TextBox {Text = "D", Top = 70});
foreach (Control control in this.Controls)
{
control.Dispose();
}
迭代器在遍历一个正在改变的集合时会跳过元素,而不抛出异常
bug?迭代器不是应该在底层集合改变时抛出 InvalidOperationException
异常吗?
所以我的问题是:为什么在改变 ControlCollection
时的迭代没有抛出 InvalidOperationException 异常?
补充:
枚举器无法独占地访问集合;因此,通过集合进行枚举本质上不是线程安全的过程。即使集合已同步,其他线程仍然可以修改集合,这会导致枚举器抛出异常。
Control
在被处理时从父级集合中移除自身的位置。 - James ThorpeRemove
方法,您可能需要先断开该链接。 - James Thorpe