为什么.NET Dictionary <tkey,tvalue =“”>不可变?</tkey,>

时间:2010-11-15 10:08:37

标签: c# .net

我声明了一个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
    }

10 个答案:

答案 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对象应该返回完全相同的数据(如果通过它们进行多次传递)。如果希望例如,这是有用的保证。产生一个包含所有项目的字符串(第一遍可以计算所有项目的长度,第二遍可以连接它们)。由于即使更改字典项的值也会违反该保证,因此禁止使用。如果一个人实际上尝试第二次通过一个集合,那么对字典值进行更改只会引起一声尖叫可能会很好,但这并不是微软设计的东西。此外,我不熟悉字典的内部实现,但它可能会将值更改作为删除和插入处理。如果它这样做,那肯定会打破一个普查员。