无法修改Dictionary的返回值,因为它不是变量

时间:2014-03-11 21:08:39

标签: c#

有这样的错误:无法修改'System.Collections.Generic.Dictionary.this [string]'的返回值,因为它不是变量。

我的代码:

Dictionary<string, lim> urlsLimited = new Dictionary<string, lim>();
struct lim
{
    public int min;
    public int max;
}
void main ()
{
    ....
    foreach (KeyValuePair<string, lim> pair in urlsLimited)
    {
        string like = od.LikeDiscussions(pair.Key);
        if (like == "Like")
        {
            lock (locker)
            {
                urlsLimited[pair.Key].min++; // error

            }
        }
    }
    ....
}

如何迭代urlsLimited [pair.Key] .min ++?

3 个答案:

答案 0 :(得分:8)

您需要将值分配给局部变量,执行增量,然后将其设置回字典。

foreach (KeyValuePair<string, lim> pair in urlsLimited)
{
    string like = od.LikeDiscussions(pair.Key);
    if (like == "Like")
    {
        lock (locker)
        {
            lim val = pair.Value;
            val.min++;
            urlsLimited[pair.Key] = val;
        }
    }
}

如需更好的解释,请参阅Jon Skeet对相关问题的回答:https://stackoverflow.com/a/6255368/1149773

答案 1 :(得分:3)

考虑这样的事情:

struct lim {
  public readonly int min;
  public readonly int max;

  public lim(int min = 0, int max = 0) {
    this.min = min;
    this.max = max;
  }
}

// ... later in your loop body
var currentLim = urlsLimited[pair.Key];
urlsLimited[pair.Key] = new lim(currentLim.min + 1, currentLim.max);

不可变的结构和明显的你正在做的事情。 :)

答案 2 :(得分:0)

Dictionary的索引器返回lim副本(因为它是一种值类型)。除非您将此副本分配给变量,否则您对min所做的任何修改都将丢失。这就是为什么您得到错误。就您而言,尽管您不想增加副本的min字段。

这些解决方案正确地表明您可以通过索引器为字典设置lim的新实例。

要记住的一点是,您已经在字典上进行迭代,因此再次在字典中搜索当前正在评估的项目似乎效率很低。您必须执行此操作,因为在迭代Dictionary时,它还会返回通过KeyValuePair保存的数据的副本,因为这也是一个值类型。类型Value的{​​{1}}也被复制到lim中,因为它也是一个值类型。

我想说,您最好将KeyValuePair从结构更改为类,因为lim的{​​{1}}属性将始终引用同一实例(而不是复制),您编写的代码将被编译,并且变得更加易于阅读。

但是,如果您确实需要在读取时获得该结构的性能提升,那么我会重新编写您的代码,以便在将值添加到字典时,您可以增加Value字段。