Ответ 1
Первый подход будет аварийно завершен во время выполнения, поскольку перечислитель гарантирует, что никто не удалит из основной коллекции при ее перечислении.
Второй подход - хорошая мысль, но словари С# являются изменяемыми и не являются ни идиоматическими, ни эффективными, чтобы копировать их, если вы можете сделать то же самое с мутацией.
Это типичный способ:
var itemsToRemove = myDic.Where(f => f.Value == 42).ToArray();
foreach (var item in itemsToRemove)
myDic.Remove(item.Key);
EDIT: ответ на ваш вопрос в комментариях. Вот как работает пример в другом вопросе:
myList = myList.where(x=>x>10).select(x=>x-10);
Эта строка кода ничего не запускает; это совершенно лениво. Скажем, ради аргумента, что после этого мы имеем foreach
, чтобы он больше напоминал этот вопрос.
foreach (int n in myList)
Console.WriteLine(n);
Когда это выполняется, вот что произойдет на каждой итерации:
- Вызов
MoveNext
в перечислении - Перечислитель находит следующее значение больше десяти
- Затем оно принимает это значение минус десять и устанавливает для свойства
Current
значение - Привязывает свойство
Current
к переменнойn
-
Console.WriteLine
это
Вы можете видеть, что нет никакой тайны и бесконечной петли, и ничего.
Теперь сравните с моим примером, предположим, что мы оставили значение ToArray
.
var itemsToRemove = myDic.Where(f => f.Value == 42);
foreach (var item in itemsToRemove)
myDic.Remove(item.Key);
- Вызов
MoveNext
в перечислении - Перечислитель находит следующую пару со значением 42 и устанавливает для свойства
Current
значение - Привязывает свойство
Current
к переменнойitem
-
Remove
это
Это не работает, потому что, хотя он отлично подходит для WriteLine
что-то из коллекции, когда у вас есть открытый счетчик, вам не разрешено Remove
что-то из коллекции, пока вы открываете счетчик он.
Если вы вызываете ToArray
спереди, вы начинаете с перечисления по словарю и заполнения массива. Когда мы переходим к foreach
, оператор foreach
имеет перечислитель, открытый в массиве, а не словарь. Вы можете удалить из словаря, когда вы перебираете массив.