不能修改Dictionary的返回值,因为它不是一个变量

本文关键字:变量 一个 Dictionary 修改 返回值 因为 不能 | 更新日期: 2023-09-27 17:49:30

出现如下错误:无法修改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++?

不能修改Dictionary的返回值,因为它不是一个变量

您需要将该值赋给一个局部变量,执行自增操作,然后将其设置回字典。

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.

考虑如下:

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);

不可变结构体,很明显你在做什么。:)

Dictionary的索引器返回lim副本(因为它是值类型)。除非您将此副本分配给变量,否则您对min所做的任何修改都将丢失。这就是你得到错误的原因。但在您的情况下,您不希望增加副本的min字段。

解决方案正确识别您可以通过索引器将lim的新实例设置到字典中。

要记住的是,此时你已经在字典中迭代了,所以再次在字典中搜索当前正在求值的项似乎非常低效。您必须这样做,因为当您迭代Dictionary时,它还返回它通过KeyValuePair保存的数据的副本,因为这也是一个值类型。lim类型的Value也被复制到KeyValuePair中,因为它也是一个值类型。

我想说你最好把lim从一个结构体变成一个类,因为这样KeyValuePairValue属性将总是引用相同的实例(而不是副本),你写的代码将编译,并且变得更容易阅读。

但是,如果你真的需要在读取时获得结构体的性能增益,那么我会重新编写代码,以便在向字典添加值时增加min字段