解决在foreach循环中替换项目的问题

时间:2011-12-16 18:51:27

标签: c# key-value

在下面的示例代码中,我想用新项替换字典中的项,或者为该项指定新值。 我该怎么做?

这是我的代码:

dynamic data = jss.Deserialize<dynamic>(jsonText);

foreach (KeyValuePair<string,object> item in data["typeData"])
{
    if(item.Key == "somevalue")
        {
            item = new KeyValuePair<string,object>();
        }                               
}

我得到了:

  

无法分配给'item',因为它是'foreach迭代变量'

必须有解决办法。

5 个答案:

答案 0 :(得分:3)

foreach被认为是只读上下文。

请勿使用foreach作为消息说明,将循环转换为常规for循环。

来自MSDN:

This error occurs when an assignment to variable occurs in a read-
only context. Read-only contexts include foreach iteration variables,
using variables, and fixed variables. To resolve this error, avoid
assignments to a statement variable in using blocks, foreach
statements, and fixed statements.

在您的情况下,对象item不是引用,只是一个副本,因此您对其所做的任何更改都不会导致原始对象发生更改。

答案 1 :(得分:2)

取决于你想要什么。你只需要覆盖这个值吗?我假设是因为替换键和值将是一个非常不同的操作(删除一个项目并插入另一个项目)

只是遍历键而不是集合(假设它是字典):

dynamic data = jss.Deserialize<dynamic>(jsonText)["typeData"];

foreach (string key in data.Keys)
{
    if(key == "somevalue")
        {
            data[key] = ...;
        }                               
}

如果没有密钥属性,你可以替换该部分(假设至少有一个索引器)

foreach (string key in data.Select(pair=>pair.Key)){
  ...
}

答案 2 :(得分:1)

您的代码存在的问题是您正在尝试更改用作占位符的变量的值。变量“item”只具有字典中存在的相同引用;更改“item”引用的对象实际上不会更改Dictionary本身中的任何内容,最重要的是它可能会破坏循环遍历Dictionary的逻辑。

除了无法重新分配占位符之外,不允许在使用所述词典的foreach循环中添加或删除Dictionary中的项目,因为这也会破坏迭代字典项目的逻辑(现在不再存在幕后枚举器“当前”项目的项目,因此枚举器可能会失去其在集合中的位置而无法继续。

解决方法是在更改原始集合时枚举其他集合。基本上,这样的任务需要两次通过;首先收集您想要更改的项目,然后通过该集合进行枚举并对原始集合进行更改:

...

var itemsToChange = new List<KeyValuePair<string, object>>();

foreach (var item in data["typeData"])
{
    if(item.Key == "somevalue")
       itemsToChange.Add(item);                                       
}

foreach(var item in itemsToChange)
{
    //even here you can't just "swap out" KVPs;
    //you must remove the old and add the new
    data["typeData"].Remove(item);
    data["typeData"].Add(someNewString, someNewObject);
}

答案 3 :(得分:1)

您必须使用for循环或存储要更改的变量,并在foreach循环之外更改它们。

答案 4 :(得分:0)

也许您的问题中缺少某些内容,但似乎解决方法是避免完全循环:

dynamic data = jss.Deserialize<dynamic>(jsonText); 
var item = new KeyValuePair<string, object>("somevalue", data["somevalue"]);

或者也许:

dynamic data = jss.Deserialize<dynamic>(jsonText);
DoSomethingWith(data["somevalue"]);

你的循环是什么原因?