当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Why is the .NET Dictionary<TKey, TValue> immutable?

问题描述:

I declared a Dictionary type object and try to add some items into it. But I cannot modify even the value of the item. It's reasonable that key should not be modifiable, but why not the value? Thanks.

 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

}

网友答案:

The dictionary itself is not immutable. But you cannot change the dictionary while enumerating it in the foreach-loop.

Here a link for further reading: Why is The Iteration Variable in a C# foreach statement read-only?

网友答案:

You are not allowed to modify the collection you are iterating over in a foreach loop. This has nothing to do with the dictionary - dict[key] = "value"; works perfectly fine outside foreach loops.

网友答案:

You're using the term immutable wrong. It's commonly used for objects which internal state won't change once they are initialized. The Dictionary<TKey, TValue> is mutable as can be. That it throws exceptions when someone tries to modify it during enumeration is an explicitely implemented behaviour.

You're probably confused why the enumeration would change when you only change a value. This isn't covered by the other answers yet.

Well, when you do

dict[key] = "something";

the enumeration will change if the key does not yet exist, because it will be added in that case, causing the enumeration to change. Surely, the dictionary implementation could check that first and allow modification if the key already exists, but I guess it follows the principle Fail early, fail often to improve over-all integrity of applications.

网友答案:

It is not immutable, you can change it, it is just that the current iterator becomes invalid if you modify the collection. You can "solve" this by forcing the iterator to complete before you modify the collection

foreach (string key in new List<string>(dict.Keys))
{
    dict[key] = "changed"; //System.InvalidOperationException: Collection was modified
}
网友答案:

Dictionary is not immutable (first, if it were, you would not be able to Add to it).

The problem is that you are trying to modify the collection while iterating over it - you cannot change a collection within a foreach block using it.

Changing values outside a foreach will work.

网友答案:

An analogy I can think of is trying to cut a tree branch while you are sitting on it. So its considered unsafe.

An alternative could be to use the for loop or clone the list.

网友答案:

You are trying to modify the collection at the same time you are iterating on it. That is not allowed. The exception is thrown by the move next method of the enumerator in foreach loop.

网友答案:

As @Femaref mentioned, you cannot change the dictionary while iterating inside a foreach loop. Another work around is to use for loop and use the following code to change it

for (int i = 0; i < dict.Count; i++)
{
    var key = dict.Keys.ElementAt(i);
    dict[key] = "changed";
}

Note: You have to use LINQ for this.

网友答案:

Microsoft decided that iEnumerable objects which support a Reset method should return exactly the same data if there are multiple passes made through them. This is a useful guarantee if one wishes to e.g. produce a string containing all the items (a first pass could tally up the length of all the items, and a second pass could concatenate them). Since even changing the value of a dictionary item would violate that guarantee, it is forbidden. It might have been nice to have changes to a dictionary value only cause a squawk if one in fact attempts a second pass through a collection, but that's not how Microsoft designed things. Also, I'm not familiar with the dictionary's internal implementation, but it's possible that it handles a Value change as a deletion and insertion. If it does that, that would certainly break an enumerator.

网友答案:

Convert dict.Keys to array.

Then do that for the loop.

If you modify collection it will throw an exception.

分享给朋友:
您可能感兴趣的文章:
随机阅读: