Благодаря Виталию я вернулся и еще раз просмотрел код, и похоже, что это конкретное решение по реализации, чтобы запретить это (см. Фрагмент ниже). Словарь сохраняет частное значение verrsion, которое увеличивается при изменении значения существующего элемента. Когда перечислитель создан, он записывает значение в это время, а затем проверяет каждый вызов 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
}
}
}