-1

我正在研究 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 参数)也从 1 更改为 10。为什么会发生这种情况,如何解决这个问题?

4

2 回答 2

2

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

于 2013-03-06T21:57:47.977 回答
1

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

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

实际上,感谢SD评论中的JG,它应该更像这样:

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

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

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 切换到一个类。

于 2013-03-06T21:58:35.227 回答