Mei*_*hes 11 .net c# foreach invalidoperationexception winforms
按照这个问题Foreach循环处理控件跳过迭代它告诉我,迭代是允许通过更改集合:
例如,以下内容:
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);
}
Run Code Online (Sandbox Code Playgroud)
投
InvalidOperationException:Collection已被修改; 枚举操作可能无法执行.
但是,在.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();
}
Run Code Online (Sandbox Code Playgroud)
它会跳过元素,因为迭代器会在更改的集合上运行,而不会抛出异常
错误?InvalidOperationException 如果底层集合发生变化,是否需要抛出迭代器?
所以我的问题是为什么迭代改变ControlCollectionNOT抛出InvalidOperationException?
附录:
枚举器没有对集合的独占访问权限; 因此,枚举通过集合本质上不是一个线程安全的过程.即使集合是同步的,其他线程仍然可以修改集合,这会导致枚举器抛出异常.
答案可以在参考资料中找到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];
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
请特别注意MoveNext()明确解决此问题的评论.
IMO这是一个被误导的"修复",因为它通过引入一个微妙的错误掩盖了一个明显的错误(如OP所指出的那样,元素被默默地跳过).
| 归档时间: |
|
| 查看次数: |
217 次 |
| 最近记录: |