我有一个A类:
public class A {
private Point[,] matrix = null;
private int r, c;
public Point[,] Matrix
{
get
{
if (this.matrix == null || this.matrix.Length == 0)
{
// Matrix is null or it has no elements on it.
return null;
}
else
{
return this.matrix;
}
}
}
public A(int r, int c)
{
this.r = r;
this.c = c;
this.matrix = new Point[r, c];
}
public void InitializeMatrix
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
this.matrix[i, j] = new Point(i, j);
}
}
}
public void CopyMatrix(out Point[,] copyMatrix)
{
if (this.Matrix == null)
{
throw new ArgumentException("Matrix is null.", "Matrix");
}
Point[,] m = new Point[r, c];
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
m[i, j] = this.Matrix[i, j];
}
}
copyMatrix = m;
}
}
Point是一个类:
public class Point
{
public int x, y;
public Point (int x, int y)
{
this.x = x;
this.y = y;
}
}
所以来自另一个班级,比方说,B:
public class B
{
private A instanceA;
public B (A a)
{
// imagine a valid not null instance of class A is passed.
this.instanceA = a;
}
private void SomeMethod()
{
Point[,] m;
this.instanceA.CopyMatrix(out m);
m[2, 4].x = 9; <--- here is the problem
Console.WriteLine(String.Format("{0}",this.instanceA.Matrix[2, 4].x));
}
}
问题是:
在B类的SomeMethod方法中,当我更新我的局部矩阵时Point [,] m也更新了A类中的矩阵'矩阵'。如果我这样做:
Console.WriteLine(this.instanceA.Matrix[2, 4]);
它也输出9。为什么?它的内容也被改变了......
答案 0 :(得分:1)
您的问题是您没有正确理解“引用”类型和“原始”类型之间的区别。
对于基本类型(数字,如int
或long
);变量本身在堆栈上分配,并包含实际的数值本身。如果我做
int foo = 1;
int bar;
bar = foo;
这为名为foo
的变量分配堆栈空间,为其赋值1
,在堆栈上为bar
分配更多空间,然后复制数字{{1}进入1
。两个变量保持彼此独立,所以如果我现在做
bar
bar = 4
保持不变。
对于一个物体,会发生一些不同的事情。请采取以下措施:
foo
在这种情况下,正在发生的事情是在堆上为class MyObject {
public int x;
}
// Inside some method somewhere
MyObject foo = new MyObject();
MyObject bar;
foo = bar;
的实例分配内存。然后在堆栈上分配名为MyObject
的引用变量,并使用刚刚创建的foo
的内存地址进行初始化。
这是一个关键点;在这种情况下,MyObject
不包含对象,只是对它的引用。这意味着当我们在下一行分配新的引用类型foo
时,行bar
现在被分配了相同分配对象的内存地址 。
这意味着我们可以执行以下操作
foo = bar
由于foo和bar现在都指向相同的内存地址,如果我们打印的值 foo.x = 1;
bar.x = 10;
或foo.x
到控制台,结果将是10。
那么,这与你的问题有什么关系?简单;您的矩阵是引用到bar.x
个对象的数组,而不是Point
个对象本身。所以代码中的行
Point
只是将这些引用复制到相同的m[i, j] = this.Matrix[i, j];
对象到新矩阵。解决你的问题;将上面的行更改为以下内容:
Point
这样做的目的是在堆上为全新的m[i, j] = new Point(this.Matrix[i, j].x, this.Matrix[i, j].y);
对象分配内存,并使用旧的值初始化它们。