在这个问题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);
}
抛出
但是,在.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();
}
跳过元素是因为迭代器在不断变化的集合上运行,而不会引发异常
漏洞?如果底层集合发生变化,是否不需要迭代器抛出
InvalidOperationException
?所以我的问题是,为什么在不断变化的
ControlCollection
上进行迭代不会引发InvalidOperationException?附录:
documentation for
IEnumerator
说:最佳答案
答案可以在the Reference Source for ControlCollectionEnumerator
中找到
private class ControlCollectionEnumerator : IEnumerator {
private ControlCollection controls;
private int current;
private int originalCount;
public ControlCollectionEnumerator(ControlCollection controls) {
this.controls = controls;
this.originalCount = controls.Count;
current = -1;
}
public bool MoveNext() {
// VSWhidbey 448276
// We have to use Controls.Count here because someone could have deleted
// an item from the array.
//
// this can happen if someone does:
// foreach (Control c in Controls) { c.Dispose(); }
//
// We also dont want to iterate past the original size of the collection
//
// this can happen if someone does
// foreach (Control c in Controls) { c.Controls.Add(new Label()); }
if (current < controls.Count - 1 && current < originalCount - 1) {
current++;
return true;
}
else {
return false;
}
}
public void Reset() {
current = -1;
}
public object Current {
get {
if (current == -1) {
return null;
}
else {
return controls[current];
}
}
}
}
请特别注意
MoveNext()
中的注释,这些注释可明确解决此问题。IMO这是一个错误的“修补程序”,因为它通过引入一个细微的错误(如OP所指出的那样,所有元素被静默跳过)掩盖了一个明显的错误。
关于c# - 为什么ControlCollection不抛出InvalidOperationException?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35084463/