Search Unity

Argument being taken as reference without "ref" keyword

Discussion in 'Scripting' started by InacioM, Jan 18, 2020.

  1. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Hey!

    So, in my app I need to consistently multiply the elements of multiple arrays, so I created a function to do that.

    The function:

    Code (CSharp):
    1.  
    2. public static class Tools
    3. {
    4.     public static int[] MultiplyArrays(int[][] Arrays)
    5.     {
    6.  
    7.         int[] ResultArray = new int[Arrays[0].Length];
    8.  
    9.         ResultArray = Arrays[0];
    10.  
    11.  
    12.         for (int i = 0; i < ResultArray.Length; i++)
    13.         {
    14.             for (int n = 1; n < Arrays.Length; n++)
    15.             {
    16.                 ResultArray[i] = ResultArray[i] * Arrays[n][i];
    17.             }
    18.  
    19.         }
    20.  
    21.         return ResultArray;
    22.     }
    23. }

    Then, say I call it with the following statement in another script:

    Code (CSharp):
    1.  
    2.         int[] array = Tools.MultiplyArrays(new int[][] { Array1, Array2 });
    The values for the variable array are being returned correctly.
    However, Array1 values are also being multiplied, even when I didn't call the int[][] argument as a ref.

    An example:

    if I call Array1 as { 10, 20 } and Array2 as { 3, 1}, I get the result array correctly as { 30, 20}, but Array1 is now also {30, 20}.

    Why is that happening?
    What can I do to correct this?


    EDIT:

    I have a similar script that sums arrays:

    Code (CSharp):
    1.     public static int[] SumArrays(int[][] Arrays)
    2.     {
    3.         int[] ResultArray = new int[Arrays[0].Length];
    4.  
    5.         for (int i = 0; i < ResultArray.Length; i++)
    6.         {
    7.             for (int n = 0; n < Arrays.Length; n++)
    8.             {
    9.                 ResultArray[i] += Arrays[n][i];
    10.             }
    11.         }
    12.  
    13.         return ResultArray;
    14.     }
    And this one works perfectly.
    So, as I understand the error lies in the line
    ResultArray = Arrays[0];


    But it's weird to me that this line is an error, since keyword ref was'nt used.
     
    Last edited: Jan 18, 2020
  2. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    I managed to find a half-answer to this.

    Arrays are always references.

    Based on this, I have replaced the line
    Code (CSharp):
    1. ResultArray = Arrays[0]
    with
    Code (CSharp):
    1.         for (int i = 0; i < ResultArray.Length; i++)
    2.         {
    3.             ResultArray[i] = Arrays[0][i];
    4.         }
    And now the code works.

    Still, I don't understand exactly why and still wonder if I can, somewhere in my code, write:
    Code (CSharp):
    1. int[] array1 = // something
    2. int[] array2 = // something else
    3.  
    4. array2 = array1;
    And then modify the array 1 without modifying array 2, and vice versa.

    Is that possible?
     
  3. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    357
    Indeed. Arrays are objects and thus by reference.

    Alternative ways to copy are:
    Code (CSharp):
    1. Array.Copy(arrayFrom, arrayTo, numItemsToCopy);
    2. arrayTo = arrayFrom.Clone() as int[];
     
    InacioM likes this.
  4. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    I see.

    I had created a static function to copy arrays, but with the methods you mentioned, they aren't necessary.

    Thanks!
     
    grizzly likes this.