在列表和数组中按索引获取struct项

bog*_*ton 7 c# arrays

当我使用一个structs 数组(例如System.Drawing.Point)时,我可以逐个索引并更改它.

例如(此代码工作正常):

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;
}
Run Code Online (Sandbox Code Playgroud)

但是当我使用List时,它不起作用:

无法修改'System.Collections.Generic.List.this [int]'的返回值,因为它不是变量

示例(此代码无法正常工作):

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;
}
Run Code Online (Sandbox Code Playgroud)

我知道当我通过索引获取列表项时,我得到了它的副本和编译器提示我没有提交错误,但为什么采用数组索引的元素工作方式不同?

Wil*_*sem 6

这是因为,对于阵列 points[i]显示,其中所述对象的位置。换句话说,points[i]数组基本上就是内存中的一个指针。因此,您可以在记录中执行操作在内存中,而不是在某个副本上。

情况并非如此List<T>:它在内部使用数组,而是通过方法进行通信,导致这些方法将从内部数组中复制值,显然修改这些副本没有多大意义:您会立即忘记它们因为您没有将副本写回内部数组。

解决这个问题的方法是,正如编译器所建议的:

(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
Run Code Online (Sandbox Code Playgroud)

所以你可以使用以下“技巧”:

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;
}
Run Code Online (Sandbox Code Playgroud)

因此,您将副本读入临时变量,修改副本,然后将其写回List<T>.