Реализация пользовательского итератора С# - предотвращение модификации коллекции во время цикла foreach

Я создал собственную коллекцию, реализующую IEnumerable(T), и пользовательскую IEnumerator(T).

Я также добавил в пользовательскую коллекцию метод Add(), который выглядит так:

public void Add(T item)
{
    T[] tempArray = new T[_array.Length + 1];

    for (int i = 0; i < _array.Length; i++)
    {
        tempArray[i] = _array[i];
    }

    tempArray[_array.Length] = item;

    _array = tempArray;
    tempArray = null;
}

Реализация основана на этом примере http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx.

Когда я выполняю цикл foreach со своим массивом, я хотел бы предотвратить модификацию коллекции (например, вызов Add() внутри цикла) и создать новое исключение InvalidOperationException. Как я смогу это сделать?


person Marko    schedule 16.11.2011    source источник


Ответы (3)


Вам нужно будет иметь идентификатор версии в вашем классе. Увеличьте его при входе на Add. Когда вы создаете итератор (в вызове GetEnumerator()), вы запоминаете номер версии - и на каждой итерации вы проверяете, остается ли номер версии тем, с чего он был в начале, иначе выбрасывается.

person Jon Skeet    schedule 16.11.2011
comment
Спасибо, Джон. Действительно простое решение. Теперь это кажется очевидным. знак равно - person Marko; 16.11.2011

Вы можете добавить в свою коллекцию поле, которое будет увеличиваться при каждом изменении коллекции. При создании перечислителя вы сохраняете значение этого поля в перечислителе. При использовании перечислителя вы проверяете, что текущее значение поля совпадает со значением, сохраненным при создании перечислителя. Если нет, вы бросаете InvalidOperationException.

person Martin Liversage    schedule 16.11.2011

Вы можете использовать список вместо временного массива в своем коде, и это все равно вызовет InvalidOperationException по умолчанию. Во-вторых, вы можете использовать общую версию IEnumerable, и вам, возможно, не придется выполнять тяжелую работу по созданию собственного итератора.

person user182630    schedule 16.11.2011