繁体   English   中英

C#复制2D矩阵问题

[英]C# Copy 2D matrix issue

我有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;
    }
}

点是一类:

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中的矩阵'matrix'。

Console.WriteLine(this.instanceA.Matrix[2, 4]);

它也输出9。 为什么? 其内容也已更改...

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

参考类型与原始类型

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

int foo = 1;
int bar;
bar = foo;

这将在堆栈上为名为foo的变量分配空间,为其分配值1 ,在堆栈上为bar分配更多空间,然后将数字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 不包含object ,只是对其的引用。 这意味着当在下一行分配新的引用类型bar ,现在为foo = bar行分配了同一分配对象内存地址

这意味着我们可以执行以下操作

foo.x = 1;
bar.x = 10;

由于foo和bar现在都指向相同的内存地址 ,如果我们 foo.xbar.x的值打印到控制台,则结果将为10。

解决方案

那么,这与您的问题有什么关系? 简单; 您的矩阵是对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);

取而代之的是在堆上为全新的Point对象分配内存,并使用旧对象中的值对其进行初始化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM