используя Linq для создания коллекции вещей, которые будут удалены из другой коллекции - PullRequest
4 голосов
/ 09 октября 2009

Мне знакома проблема изменения коллекции при ее циклическом цикле foreach (т. Е. «System.InvalidOperationException: Коллекция была изменена»). Однако для меня не имеет смысла, что когда я использую Linq для создания Списка ключей для удаления из словаря, а затем зацикливаю свой новый Список, я получаю то же исключение.

Код до того, что сгенерировал исключение:

IEnumerable<Guid> keysToDelete = _outConnections.Where(
    pair => pair.Value < timeoutPoint
).Select(pair => pair.Key);

foreach (Guid key in keysToDelete)
{
    ...some stuff not dealing with keysToDelete...
    _outConnections.Remove(key);
}

Код после того, что сработало:

List<Guid> keysToDelete = _outConnections.Where(
    pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();

for (int i=keysToDelete.Count-1; i>=0; i--)
{
    Guid key = keysToDelete[i];
    ...some stuff not dealing with keysToDelete...
    _outConnections.Remove(key);
}

Почему это? У меня такое ощущение, что, возможно, мои запросы Linq на самом деле не возвращают новую коллекцию, а скорее некоторые поднаборы исходной коллекции, поэтому он обвиняет меня в изменении коллекции keysToDelete, когда я удаляю элемент из _outConnections.

Обновление: следующее исправление также работает, благодаря Адаму Робинсону:

List<Guid> keysToDelete = _outConnections.Where(
    pair => pair.Value < timeoutPoint
).Select(pair => pair.Key).ToList();

foreach (Guid key in keysToDelete)
{
    ...some stuff not dealing with keysToDelete...
    _outConnections.Remove(key);
}

1 Ответ

9 голосов
/ 09 октября 2009

Ты прав. LINQ использует то, что называется «отложенное выполнение». Объявление вашего запроса LINQ на самом деле ничего не делает , кроме создания выражения запроса. Только когда вы фактически перечислите список, запрос будет оценен, и он использует исходный список в качестве источника.

Однако, вызов ToList() должен создать новый список, который не имеет отношения к оригиналу. Проверьте стек вызовов вашего исключения, чтобы убедиться, что он на самом деле выбрасывается keysToDelete.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...