简体   繁体   English

C#复制2D矩阵问题

[英]C# Copy 2D matrix issue

I have a class A: 我有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 is a class: 点是一类:

public class Point 
{
    public int x, y;

    public Point (int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

So from another class, let's say, B: 因此,从另一个类,我们说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));
     }
}

The problem is: 问题是:

In SomeMethod method of class B, when I update my local matrix Point[,] m also is updated matrix 'matrix' in class A. If I do: 在类B的SomeMethod方法中,当我更新本地矩阵Point [,] m时,也更新了类A中的矩阵'matrix'。

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

it outputs 9 as well. 它也输出9。 Why? 为什么? Its content has been altered as well... 其内容也已更改...

Your issue here is that you don't properly understand the difference between a 'reference' type and a 'primitive' type. 这里的问题是您没有正确理解“引用”类型和“原始”类型之间的区别。

Reference Types vs. Primitive Types 参考类型与原始类型

For a primitive type (numbers, like an int or a long ); 对于基本类型(数字,例如intlong ); the variable itself is allocated on the stack and contains the actual numerical value itself. 变量本身分配在堆栈上,并包含实际数值本身。 If I do 如果我做

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

This allocates space on the stack for a variable named foo , assigns it the value 1 , allocates more space on the stack for bar , then copies the number 1 into bar . 这将在堆栈上为名为foo的变量分配空间,为其分配值1 ,在堆栈上为bar分配更多空间,然后将数字1复制到bar Both variables remain independent of each other, so if I now do 这两个变量保持彼此独立,所以如果我现在这样做

bar = 4

foo remains unchanged. foo保持不变。

For an object, something a little different is happening. 对于一个对象,正在发生一些不同的事情。 Take the following: 采取以下措施:

class MyObject {
    public int x;
}


// Inside some method somewhere
MyObject foo = new MyObject();
MyObject bar;
foo = bar;

In this case what is happening is memory is allocated on the heap for an instance of MyObject . 在这种情况下,正在为MyObject实例在堆上分配内存。 A reference variable named foo is then allocated on the stack and initialised with the memory address of the MyObject that was just created. 然后,将一个名为foo引用变量分配到堆栈上,并使用刚刚创建的MyObject内存地址进行初始化。

This is a crucial point; 这是关键点; in this instance foo does not contain the object , simply a reference to it. 在这种情况下, foo 不包含object ,只是对其的引用。 This means when on the next line we allocate a new reference type bar , the line foo = bar is now assigned the memory address of the same allocated object . 这意味着当在下一行分配新的引用类型bar ,现在为foo = bar行分配了同一分配对象内存地址

This means we can do the following 这意味着我们可以执行以下操作

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

Since foo and bar now both point to the same memory address , if we were to print the value of either foo.x or bar.x to the console, the outcome would be 10. 由于foo和bar现在都指向相同的内存地址 ,如果我们 foo.xbar.x的值打印到控制台,则结果将为10。

The Solution 解决方案

SO, how does this relate to your problem? 那么,这与您的问题有什么关系? Easy; 简单; your matrix is an array of references to Point objects, not Point objects themselves. 您的矩阵是对Point对象的引用数组,而不是Point对象本身。 So the line in your code 所以你的代码行

m[i, j] = this.Matrix[i, j];

Is simply copying these references to the same Point objects to the new matrix. 只是将这些对相同Point对象的引用复制到新矩阵中。 To solve your problem; 解决您的问题; change the above line to the following: 将上面的行更改为以下内容:

m[i, j] = new Point(this.Matrix[i, j].x, this.Matrix[i, j].y);

What this does instead is to allocate memory on the heap for entirely new Point objects, and initialise them with the values from the old ones. 取而代之的是在堆上为全新的Point对象分配内存,并使用旧对象中的值对其进行初始化。

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

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