Po tym pytaniu Foreach loop for disposing controls skipping iterations to podsłuch mi, że iteracja pozwolono na zmieniającej się kolekcji:Dlaczego funkcja ControlCollection NIE rzuca wyjątku InvalidOperationException?
Na przykład następujący:
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);
}
rzuca
InvalidOperationException: Kolekcja została zmodyfikowana; operacja wyliczania może nie zostać wykonana.
Jednak w .Net Formularza można zrobić:
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();
}
który pomija elementy ponieważ iterator biegnie nad zmieniającym kolekcji, bez rzuca wyjątek
błąd? czy iteratory nie są wymagane do rzucenia InvalidOperationException
, jeśli kolekcja podkładania się zmieni?
Moje pytanie brzmi: Dlaczego iteracja zmieniającego się ControlCollection
NIE powoduje odrzucenia wyjątku InvalidOperationException?
Uzupełnienie:
Dokumentacja IEnumerator
mówi:
moduł wyliczający nie mają wyłączny dostęp do kolekcji; dlatego wyliczanie poprzez kolekcję nie jest samoistnie procedurą bezpieczną dla wątków. Nawet jeśli kolekcja jest zsynchronizowana, inne wątki nadal mogą modyfikować kolekcję, , co powoduje, że moduł wyliczający wyrzuca wyjątek.
https://msdn.microsoft.com/en-us/library/system.collections.ienumerator%28v=vs.100%29.aspx
robi 'this.Controls.Count' po zakończeniu" foreach "? Myślę, że controllCollection się nie zmienia. –
@AmitKumarGhosh Tak, ponieważ ControllsCollection przestawia indeks pozostałych kontrolek po każdym wywołaniu funkcji 'Control.ControlCollection.Remove()' – Marco
Nie wszystkie kolekcje implementują tę funkcję. –