简体   繁体   中英

C# Copy 2D matrix issue

I have a class 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:

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:

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

it outputs 9 as well. 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 ); 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 . Both variables remain independent of each other, so if I now do

bar = 4

foo remains unchanged.

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 . A reference variable named foo is then allocated on the stack and initialised with the memory address of the MyObject that was just created.

This is a crucial point; in this instance foo does not contain the object , simply a reference to it. 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 .

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.

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. 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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