C#复制2D矩阵问题

时间:2017-02-26 17:22:47

标签: c# matrix

我有一个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。为什么?它的内容也被改变了......

1 个答案:

答案 0 :(得分:1)

您的问题是您没有正确理解“引用”类型和“原始”类型之间的区别。

参考类型与原始类型

对于基本类型(数字,如intlong);变量本身在堆栈上分配,并包含实际的数值本身。如果我做

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); 对象分配内存,并使用旧的值初始化它们。