Have such error: Cannot modify the return value of 'System.Collections.Generic.Dictionary.this[string]' because it is not a variable.`
My code:
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
}
}
}
....
}
How to iterate urlsLimited[pair.Key].min++?
You will need to assign the value to a local variable, perform the increment, then set it back to the 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;
}
}
}
For a good explanation, refer to Jon Skeet's answer on a related question: https://stackoverflow.com/a/6255368/1149773.
Consider something like this:
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);
Immutable struct and obvious what you're doing. :)
The indexer of the Dictionary
returns a copy of lim
(because it is a value type). Unless you assign this copy to a variable then any modifications you make to min
will be lost. This is why you are getting the error. In your case though you do not want to increment the min
field of a copy.
The solutions correctly identify that you can set a new instance of lim
to the dictionary via the indexer.
The thing to remember is that you are already iterating over the dictionary at this point, so it seems very inefficient to be then searching the dictionary again for the very item you are currently evaluating. You have to do this because when you iterate the Dictionary
this also returns a copy of the data it holds via a KeyValuePair
, since that is also a value type. The Value
of type lim
is also copied into the KeyValuePair
since it is a value type too.
I would say that you are better off changing lim
from a struct to a class, because then the Value
property of the KeyValuePair
will then always reference the same instance (not a copy), the code you have written will compile, and become a lot easier to read too.
However if you really need that performance gain of the struct on the reads then I would rework your code so that at the time of adding the values to your dictionary you increment the min
field.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With