gpt4 book ai didi

c# - 为什么 ControlCollection 不抛出 InvalidOperationException?

转载 作者:可可西里 更新时间:2023-11-01 08:43:27 24 4
gpt4 key购买 nike

跟随这个问题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: Collection was modified; enumeration operation may not execute.

但是在 .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 enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads can still modify the collection, which causes the enumerator to throw an exception.

最佳答案

这个问题的答案可以在 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/

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