У мене є класичний випадок спроби видалити елемент із колекції, перераховуючи його в циклі:
List<int> myIntCollection = new List<int>();
myIntCollection.Add(42);
myIntCollection.Add(12);
myIntCollection.Add(96);
myIntCollection.Add(25);
foreach (int i in myIntCollection)
{
if (i == 42)
myIntCollection.Remove(96); // The error is here.
if (i == 25)
myIntCollection.Remove(42); // The error is here.
}
На початку ітерації після того, як відбулася зміна, InvalidOperationException
кидається an , тому що перечислювачі не люблять, коли базова колекція змінюється.
Мені потрібно внести зміни до колекції під час ітерації. Існує багато шаблонів, які можна використовувати, щоб уникнути цього , але, здається, жоден з них не має гарного рішення:
Не видаляйте всередині цього циклу, натомість тримайте окремий “Видалити список”, який ви обробляєте після основного циклу.
Зазвичай це хороше рішення, але в моєму випадку мені потрібно, щоб елемент негайно зник, оскільки “чекає”, поки основний цикл дійсно видалить елемент, що змінює логічний потік мого коду.
Замість того, щоб видаляти елемент, просто встановіть прапор на ньому та позначте його як неактивний. Потім додайте функціональність шаблону 1, щоб очистити список.
Це буде працювати на всі мої потреби, але це означає, що багато коду доведеться змінити, щоб перевіряти неактивний прапор кожного разу, коли доступ до елемента. Це занадто багато адміністрації на мій смак.
Якось включіть ідеї зразка 2 у клас, який походить від
List<T>
. Цей Суперліст буде обробляти неактивний прапор, видалення об’єктів після факту, а також не буде виставляти елементи, позначені як неактивні, для переліку споживачів. По суті, він просто інкапсулює всі ідеї зразка 2 (і згодом зразка 1).Чи існує такий клас? Хтось має код для цього? Або є кращий спосіб?
Мені сказали, що доступ
myIntCollection.ToArray()
замістьmyIntCollection
вирішить проблему і дозволить мені видалити всередині циклу.Мені це здається поганим шаблоном дизайну, а може, це добре?
Подробиці:
Список буде містити багато елементів, і я буду вилучати лише деякі з них.
Усередині циклу я буду виконувати всілякі процеси, додавати, видаляти тощо, тому рішення має бути досить загальним.
Елемент, який мені потрібно видалити, може не бути поточним елементом у циклі. Наприклад, я можу потрапити до пункту 10 циклу з 30 елементів, і мені потрібно видалити елемент 6 або пункт 26. Проходження назад через масив через це більше не працюватиме. ; o (