Pointer problem with List<double[]>

Andreas ss 726 Reputation points
2022-01-24T18:50:10.937+00:00

Hello!

I have a little problem with below list2 which I beleive keeps a pointer for some reason.

First I add an array like this to list2:

double[] val = new double[1]; val[0] = 0.5;  list2.Add(val);

Then I "remember" this list2 in original_list2 like this:

List<double[]> original_list2 = new List<double[]>(list2);

Then I change value like this:

list2[0][0] = 0.2;

Then I need to change BACK to how the list2 was from the beginning like this:

list2 = new List<double[]>(original_list2); //Does NOT work and keeps the "0.2" change???

But this is where the problem occurs that, list2[0][0] now still shows 0.2 when I want it to show 0.5 which was the orignal value in the list2.
Somhow this must create a pointer. But I don't know if there is an elegant solution of how to "remember this list2" in the step I do that?

As seen in the code below, the idéa works for List<double> list1 but not for List<double[]> list2 which I try to do?

Thank you!

            //Create list1 and list2
            List<double> list1 = new List<double>();
            list1.Add(0.5);

            List<double[]> list2 = new List<double[]>();
            double[] val = new double[1]; val[0] = 0.5;
            list2.Add(val);



            //Remember the values in list1 and list2 before "CHANGE value in lists"
            List<double> original_list1 = new List<double>(list1);
            List<double[]> original_list2 = new List<double[]>(list2);


            //CHANGE value in lists
            list1[0] = 0.2;
            list2[0][0] = 0.2;



            //Now we need to put back the list1 and list2 how they were when: "Create list1 and list2"
            list1 = new List<double>(original_list1); //Works and changes back correctly!
            list2 = new List<double[]>(original_list2); //Does NOT work and keeps the "0.2" change???


            MessageBox.Show(list1[0] + "\n" + //Works and changes back correctly!
                            list2[0][0]); //Does NOT work and keeps the "0.2" change???
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,521 questions
0 comments No comments
{count} votes

Accepted answer
  1. P a u l 10,411 Reputation points
    2022-01-24T19:10:53.333+00:00

    double is a value type whereas double[] is a reference type, and when you pass a value type to a variable, or into a method, etc.. it will copy the value. When you pass a reference type to a method it will copy the reference but not the underlying value. Ultimately you will have multiple references to the same object.

    The issue that you're seeing here is that you have two lists where the first element refers to the same array instance in memory. If you want to change values to an array then you'll need to create a shallow copy of it. A shallow copy means that the array itself will be cloned, but the items within the array will remain the same.

    Once you've cloned your array you can alter the values in the new array all you like and it won't affect the original array. Here's a snippet to demonstrate the issue you're noticing & also how you can fix it:

    Without the cloning:

    {
        double[] arr = new[] { 0.5 };
    
        List<double[]> list1 = new() { arr };
        List<double[]> list2 = new() { arr };
    
        // This affects both list1 and list2 because they hold the *same* "double[]" 
        // in their first elements.
        list1[0][0] = 0.2;
    
        Console.WriteLine(list2[0][0]);
    }
    

    Prints: 0.2

    With the cloning:

    {
        double[] arr = new[] { 0.5 };
    
        List<double[]> list1 = new() { (double[])arr.Clone() };
        List<double[]> list2 = new() { (double[])arr.Clone() };
    
        // This only affects the clone in list1, leaving list2 and the underlying original array unaffected 
        // in their first elements.
        list1[0][0] = 0.2;
    
        Console.WriteLine(list2[0][0]);
    }
    

    Prints: 0.5


0 additional answers

Sort by: Most helpful