我声明了一个Dictionary类型对象,并尝试在其中添加一些项目。但我甚至不能修改项目的价值。密钥不应该是可修改的,但为什么不是值?感谢。
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("1", "bob");
dict.Add("2", "jack");
dict.Add("3", "wtf");
foreach (string key in dict.Keys)
{
dict[key] = "changed"; //System.InvalidOperationException: Collection was modified
}
答案 0 :(得分:17)
您不能修改您在foreach
循环中迭代的集合。这与字典无关 - dict[key] = "value";
在foreach
循环之外完美无缺。
答案 1 :(得分:14)
字典本身并不是一成不变的。但是你不能在foreach循环中枚举字典时更改字典。
以下是进一步阅读的链接:Why is The Iteration Variable in a C# foreach statement read-only?
答案 2 :(得分:7)
您使用的术语immutable错误。它通常用于内部状态初始化后不会改变的对象。 Dictionary<TKey, TValue>
是可变的。当有人在枚举期间尝试修改异常时,它会抛出异常,这是一种明显实现的行为。
当您只更改值时,您可能会混淆为什么枚举会发生变化。其他答案尚未涵盖这一点。
嗯,当你做的时候
dict[key] = "something";
枚举将 更改 。当然,如果密钥已经存在,字典实现可以先检查并允许修改,但我想它遵循早期失败原则,经常失败来提高应用程序的整体完整性。
答案 3 :(得分:4)
它不是不可变的,你可以改变它,只是当你修改集合时当前的迭代器变得无效。您可以通过在修改集合
之前强制完成迭代器来“解决”这个问题foreach (string key in new List<string>(dict.Keys))
{
dict[key] = "changed"; //System.InvalidOperationException: Collection was modified
}
答案 4 :(得分:2)
Dictionary
不不可变(首先,如果是,您将无法Add
)。
问题是你试图在迭代它时修改集合 - 你无法使用它来更改foreach
块内的集合。
更改foreach
之外的值将有效。
答案 5 :(得分:2)
我能想到的一个类比就是在你坐在树枝上时试图砍树枝。所以它被认为是不安全的。
另一种方法是使用for循环或克隆列表。
答案 6 :(得分:1)
您正在尝试在迭代它的同时修改集合。这是不允许的。 foreach循环中枚举器的move next方法抛出异常。
答案 7 :(得分:1)
正如@Femaref所提到的,在foreach循环内迭代时无法更改字典。另一个解决方法是使用for循环并使用以下代码进行更改
for (int i = 0; i < dict.Count; i++)
{
var key = dict.Keys.ElementAt(i);
dict[key] = "changed";
}
注意:您必须使用LINQ。
答案 8 :(得分:1)
将dict.Keys
转换为数组。
然后为循环执行此操作。
如果修改集合,则会抛出异常。
答案 9 :(得分:1)
Microsoft决定支持Reset方法的iEnumerable对象应该返回完全相同的数据(如果通过它们进行多次传递)。如果希望例如,这是有用的保证。产生一个包含所有项目的字符串(第一遍可以计算所有项目的长度,第二遍可以连接它们)。由于即使更改字典项的值也会违反该保证,因此禁止使用。如果一个人实际上尝试第二次通过一个集合,那么对字典值进行更改只会引起一声尖叫可能会很好,但这并不是微软设计的东西。此外,我不熟悉字典的内部实现,但它可能会将值更改作为删除和插入处理。如果它这样做,那肯定会打破一个普查员。