C # пользовательская реализация Iterator - предотвратить изменение коллекции во время цикла foreach - PullRequest
3 голосов
/ 16 ноября 2011

Я создал пользовательскую коллекцию, которая реализует 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. Как я смогу это сделать?

Ответы [ 3 ]

5 голосов
/ 16 ноября 2011

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

4 голосов
/ 16 ноября 2011

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

1 голос
/ 16 ноября 2011

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

...