Почему мы не можем изменить Значения словаря при перечислении его ключей?

Вы можете попробовать другие X-серверы в Windows, такие как xwin32 и hummingbird. Обратите внимание, что это коммерческие реализации.

Другим решением является установка сервера виртуальных машин на вашем компьютере с Windows и установка Linux на виртуальной машине. Варианты включают VMware (не бесплатно) и Microsoft Virtual PC (бесплатная загрузка). VMware намного лучше, чем VirtualPC (64-битная поддержка, больше стимулов для поддержки клиентских ОС Linux и т. Д.). Там также может

26
задан Cœur 16 April 2017 в 04:16
поделиться

7 ответов

На самом деле я понимаю, откуда вы. Большинство ответов здесь не замечают, что вы выполняете итерацию по списку ключей, а не по самим элементам словаря. Если бы программисты .NET Framework захотели, они могли бы довольно легко различать изменения, внесенные в структуру словаря, и изменения, внесенные в значения в словаре. Тем не менее, даже когда люди перебирают ключи коллекции, они обычно все равно получают значения. Я подозреваю, что разработчики .NET framework посчитали, что если вы повторяете эти значения, вы захотите узнать, не меняет ли их что-то из-под вас, так же, как и с любым List. Либо так, либо они этого не сделали

7
ответ дан 28 November 2019 в 07:18
поделиться

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

Обязательно ли изменение значения меняет порядок базовой структуры? Нет. Но это специфическая деталь реализации, и класс Dictionary , правильно, считает, что не раскрывает это, разрешая изменение значений как часть API.

19
ответ дан 28 November 2019 в 07:18
поделиться

Благодаря Виталию я вернулся и еще раз просмотрел код, и похоже, что это конкретное решение реализации, запрещающее это (см. Фрагмент ниже). Словарь хранит частное значение, называемое версией, которое увеличивается при изменении значения существующего элемента. Когда перечислитель создается, он записывает значение на тот момент, а затем проверяет каждый вызов MoveNext.

for (int i = this.buckets[index]; i >= 0; i = this.entries[i].next)
{
    if ((this.entries[i].hashCode == num) && this.comparer.Equals(this.entries[i].key, key))
    {
        if (add)
        {
            ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
        }
        this.entries[i].value = value;
        this.version++;
        return;
    }
}

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

public class IntWrapper
{
  public IntWrapper(int v) { Value = v; }
  public int Value { get; set; }
}

class Program
{
  static void Main(string[] args)
  {
    var kvp = new KeyValuePair<string, int>("1",1);
    kvp.Value = 17;
    var dictionary = new Dictionary<string, IntWrapper>(){
      {"1", new IntWrapper(1)}, 
      {"2", new IntWrapper(2)}, 
      {"3", new IntWrapper(3)} };

    foreach (var s in dictionary.Keys)
    {
      dictionary[s].Value = 1;  //OK
      dictionary[s] = new IntWrapper(1); // boom
    }
  } 
}
7
ответ дан 28 November 2019 в 07:18
поделиться

Возможно, вы только что вставили новый ключ в словарь, который действительно изменит dictionary.Keys . Несмотря на то, что в этом конкретном цикле этого никогда не произойдет, операция [] в целом может изменить список ключей, поэтому это помечается как мутация.

5
ответ дан 28 November 2019 в 07:18
поделиться

Индексатор в Словаре потенциально является операцией, которая может изменить структуру коллекции, поскольку она добавит новую запись с таким ключом, если таковая еще не существует. Очевидно, здесь дело обстоит не так, но я ожидаю, что контракт Dictionary намеренно сделан простым, поскольку все операции над объектом делятся на «изменяющие» и «неизменяемые», а все «изменяющие» операции делают счетчики недействительными, даже если они фактически ничего не меняют.

4
ответ дан 28 November 2019 в 07:18
поделиться

Из документации (Свойство Dictionary.Item):

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

Итак, как указывает Джон, у платформы нет способа узнать, что вы не изменили содержимое списка, поэтому предполагается, что вы это сделали.

1
ответ дан 28 November 2019 в 07:18
поделиться

Короткий ответ заключается в том, что вы изменяете коллекцию словарей, даже если вы ' re фактически не меняет ни один из своих ключей.

0
ответ дан 28 November 2019 в 07:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: