Применение функции к коллекции значений словаря

#c# #.net

#c# #.net

Вопрос:

 foreach (string key in dbFields.Keys)
     dbFields[key] = MySqlHelper.EscapeString(dbFields[key]);
  

Я получаю ошибку InvalidOperationException, утверждающую, что коллекция была изменена. Почему он думает, что коллекция ключей была изменена?

Я просто хочу применить функцию ко всем значениям словаря -_-

Я знаю, что смогу это сделать, если использую второй словарь. Мне просто интересно, существует ли строгий упрощенный элегантный способ изменить все значения в словаре (без явного создания второго).

Ответ №1:

Попробуйте это:

 foreach (string key in dbFields.Keys.ToList())
     dbFields[key] = MySqlHelper.EscapeString(dbFields[key]);
  

Вы не можете изменять коллекцию, по которой выполняете итерацию, ToList() в этом случае для вас будет создана новая List<string> , по которой вы выполняете итерацию, поэтому вы можете безопасно изменять словарь.

Что касается комментария — из MSDN:

Словарь.Сбор ключей — это не статическая копия; вместо этого словарь.KeyCollection ссылается обратно на ключи в исходном словаре. Следовательно, изменения в словаре продолжают отражаться в словаре.Сбор ключей.

Таким образом, это зависит от реализации индексатора ( dbFields[key] = ... ), считает ли словарь, что коллекция ключей изменена (очевидно, это так, поскольку есть исключение) — к сожалению, у меня нет Reflector под рукой в данный момент, иначе я мог бы просто проверить.

Комментарии:

1. Что меня смущает — разве коллекция ключей не отличается от коллекции значений?

2. Когда можно изменить коллекцию ключей, присвоив значение с помощью dbFields[newkey]. поэтому при выполнении такого назначения вы получаете исключение.

3. @Volkmar — технически это не новый ключ, хотя он изменяет значение для существующего ключа.

4. Настройка через индексатор вызывает into set_Item , который вызывает INTO Insert , и именно здесь я теряюсь в IL. У меня также нет Reflector на моей машине.