When I use an array of struct
s (for example System.Drawing.Point), I can get item by index and change it.
For example (This code work fine):
Point[] points = new Point[] { new Point(0,0), new Point(1,1), new Point(2,2) };
for (int i = 0; i < points.Length; i++)
{
points[i].X += 1;
}
but when i use List it's not work:
Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable
Example(This code didn't work fine):
List<Point> points = new List<Point> { new Point(0,0), new Point(1,1), new Point(2,2) };
for (int i = 0; i < points.Count; i++)
{
points[i].X += 1;
}
I know that when I get list item by index I got copy of it and compiler hints that I did not commit an error, but why take the elements of the array index works differently?
This is because for the array points[i]
shows where the object is located. In other words, basically points[i]
for an array is a pointer in memory. You thus perform operations on-the-record in memory, not on some copy.
This is not the case for List<T>
: it uses an array internally, but communicates through methods resulting in the fact that these methods will copy the values out of the internal array, and evidently modifying these copies does not make much sense: you immediately forget about them since you do not write the copy back to the internal array.
A way to solve this problem is, as the compiler suggests:
(3,11): error CS1612: Cannot modify a value type return value of `System.Collections.Generic.List<Point>.this[int]'. Consider storing the value in a temporary variable
So you could use the following "trick":
List<Point> points = new List<Point> { new Point(0,0), new Point(1,1), new Point(2,2) };
for (int i = 0; i < points.Count; i++) {
Point p = points[i];
p.X += 1;
points[i] = p;
}
So you read the copy into a temporary variable, modify the copy, and write it back to the List<T>
.
The reason is that structs are value types so when you access a list element you will in fact access an intermediate copy of the element which has been returned by the indexer of the list.
Other words, when using the List<T>
, you're are creating copies.
MSDN
Error Message
Cannot modify the return value of 'expression' because it is not a variable
An attempt was made to modify a value type that was the result of an intermediate expression. Because the value is not persisted, the value will be unchanged.
To resolve this error, store the result of the expression in an intermediate value, or use a reference type for the intermediate expression.
Solution:
List<Point> points = new List<Point> { new Point(0,0), new Point(1,1), new Point(2,2) };
for (int i = 0; i < points.Count; i++)
{
Point p = points[i];
p.X += 1;
//and don't forget update the old value, because we're using copy
points[i] = p;
}
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