为什么在结构中更改数组所有引用都会改变?

时间:2013-03-06 21:52:25

标签: c# list

我正在研究C#项目,我的代码是这样的:

public struct Point
{
    public int X;
    public int[,] arr;
}
List<Point> po=new List<Point>();
void func()
{
    Point p1;
    p1.arr = new int[1, 1];
    p1.X = 10;
    p1.arr[0, 0] = 1;
    func2(p2);
    p1.X=20;
    p1.arr[0,0]=10;
 }
void func2(Point h)
    {
        po.Add(h);
    }

当我跟踪这段代码并从func2返回时,当更改p1.x时,我的列表中的点(x参数)没有改变但是当将p1.arr改为10时,我的点(arr parametr)在列表中也从1改变为什么这发生了怎样才能解决这个问题?

2 个答案:

答案 0 :(得分:2)

结构具有价值语义。这意味着更改p1.x正在更改值,而不是引用。您有一个正在更改的本地值p1。当您在数组中更改值时,您正在更改该值的副本。

答案 1 :(得分:1)

结构是C#中的值类型,而类是引用。尝试使用ref修饰符将点传递给func2。

void func2(ref Point h){
    ....
}

实际上,多亏了SD的评论中的JG,它应该更像是这样:

void func2(ref Point po, Point h){
    po.Add(h);
}

在进一步审查时,这仍然是错误的。基本上,当您将Point添加到List时,它会将Point by值复制到列表中。

p1和po.Last()具有相同的值,但引用不同的对象。如果Point是一个类,你就不会遇到这个问题。

你可以在将p1添加到po之后立即执行此操作,但它是愚蠢和笨拙的:

po.Add(p1);
var len = po.Count;
po[len-1].X = 20;
po[len-1].arr[0,0]=10;

你做不到:

po.Add(p1);
var len = po.Count;
var pNew = po[len-1]; 
// p1 and pNew are different objects in memory, but with the same values
pNew.X = 20;
pNew.arr[0,0]=10;

嗯,从技术上讲,你可以做到这一点,但由于它们在内存中是不同的对象,它不会做你所希望的。

只要将Point切换到一个类,除非你真的不需要这样做。