在foreach循环中替换item

本文关键字:替换 item 循环 foreach | 更新日期: 2023-09-27 18:18:00

在下面的示例代码中,我想用新项替换字典中的项或为该项分配新值。我怎么能做到这一点?

这是我的代码:

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迭代变量'

在foreach循环中替换item

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不是引用,它只是一个副本,因此您对它所做的任何更改都不会导致原始对象的更改。

取决于你想要什么。您只需要重写该值吗?我认为是这样的,因为替换键和值将是一个非常不同的操作(删除一个项并插入另一个项)

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

dynamic data = jss.Deserialize<dynamic>(jsonText)["typeData"];
foreach (string key in data.Keys)
{
    if(key == "somevalue")
        {
            data[key] = ...;
        }                               
}

如果没有keys属性你可以用

(假设至少有索引器)代替
foreach (string key in data.Select(pair=>pair.Key)){
  ...
}

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

除了不能重新赋值占位符之外,还不允许在使用上述Dictionary的foreach循环中向Dictionary中添加或删除项,因为这也会扰乱遍历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);
}

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

也许你的问题中缺少了一些东西,但似乎解决方法是完全避免循环:

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

或者:

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

循环的原因是什么?