user3818372
user3818372

Reputation: 61

Passing Arrays as Arguments

In the following example, an array of strings is initialized and passed as an argument to a PrintArray method for strings. The method displays the elements of the array. Next, methods ChangeArray and ChangeArrayElement are called to demonstrate that sending an array argument by value does not prevent changes to the array elements. My question is how the array didn't change in the method changeArray.. but changed in the method ChangeArrayElements? here's the example:

class ArrayClass
{
    static void PrintArray(string[] arr)
    {
        for (int i = 0; i < arr.Length; i++)
        {
            System.Console.Write(arr[i] + "{0}", i < arr.Length - 1 ? " " : "");
        }
        System.Console.WriteLine();
    }

    static void ChangeArray(string[] arr)
    {
        // The following attempt to reverse the array does not persist when 
        // the method returns, because arr is a value parameter.
        arr = (arr.Reverse()).ToArray();
        // The following statement displays Sat as the first element in the array.
        System.Console.WriteLine("arr[0] is {0} in ChangeArray.", arr[0]);
    }

     static void ChangeArrayElements(string[] arr)
    {
        // The following assignments change the value of individual array  
        // elements. 
        arr[0] = "Sat";
        arr[1] = "Fri";
        arr[2] = "Thu";
        // The following statement again displays Sat as the first element 
        // in the array arr, inside the called method.
        System.Console.WriteLine("arr[0] is {0} in ChangeArrayElements.", arr[0]);
    }

    static void Main()
    {
        // Declare and initialize an array. 
        string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

        // Pass the array as an argument to PrintArray.
        PrintArray(weekDays);

        // ChangeArray tries to change the array by assigning something new 
        // to the array in the method. 
        ChangeArray(weekDays);

        // Print the array again, to verify that it has not been changed.
        System.Console.WriteLine("Array weekDays after the call to ChangeArray:");
        PrintArray(weekDays);
        System.Console.WriteLine();

        // ChangeArrayElements assigns new values to individual array 
        // elements.
        ChangeArrayElements(weekDays);

        // The changes to individual elements persist after the method returns. 
        // Print the array, to verify that it has been changed.
        System.Console.WriteLine("Array weekDays after the call to      ChangeArrayElements:");
        PrintArray(weekDays);
    } 
}
// Output:  
// Sun Mon Tue Wed Thu Fri Sat 
// arr[0] is Sat in ChangeArray. 
// Array weekDays after the call to ChangeArray: 
// Sun Mon Tue Wed Thu Fri Sat 
//  
// arr[0] is Sat in ChangeArrayElements. 
// Array weekDays after the call to ChangeArrayElements: 
// Sat Fri Thu Wed Thu Fri Sat

Upvotes: 0

Views: 454

Answers (1)

D Stanley
D Stanley

Reputation: 152644

In this method:

static void ChangeArray(string[] arr)
{
    // The following attempt to reverse the array does not persist when 
    // the method returns, because arr is a value parameter.
    arr = (arr.Reverse()).ToArray();
    // The following statement displays Sat as the first element in the array.
    System.Console.WriteLine("arr[0] is {0} in ChangeArray.", arr[0]);
}

You are not changing the source array - you are creating a new array and saving the reference in the same variable.

Since the reference in arr is passed by value, the caller still has a reference to the original array - the fact that you have a new reference to the reversed array does not change the reference that the caller has.

By contract, in ChangeArrayElements you are changing the array that was passed in, so the caller sees those changes.

If the array reference was passed by reference:

static void ChangeArray(ref string[] arr)
{
    // Since 'arr' is passed by reference, changing the value of 'arr'
    // changes the reference that the caller has.
    arr = (arr.Reverse()).ToArray();
    // The following statement displays Sat as the first element in the array.
    System.Console.WriteLine("arr[0] is {0} in ChangeArray.", arr[0]);
}

Then the caller would see the change since you would be changing the reference that the caller is holding.

Here's a story (hopefully) illustrating the difference:

Passing reference types by value:

  • Main - asks the universe for an array - universe tells it "the array is in slot 1".
  • Main - writes a 1 on a sticky note labeled "weekDays"
  • Main - tells ChangeArray that there is an array at slot 1.
  • ChangeArray - writes down the number 1 on a sticky note labeled arr.
  • ChangeArray - asks the universe to Reverse the array. The universe reverses the array and tells ChangeArray that the new array is in slot 2.
  • ChangeArray - crosses out the 1 on the sticky note labeled arr and writes a 2.

As you can see, since Reverse does not change the original array, the array that the caller has a reference to does not change.

Passing reference types by reference:

  • Main - asks the universe for an array - universe tells it "the array is in slot 1".
  • Main - writes a 1 on a sticky note labeled "weekDays"
  • Main - hands ChangeArray the sticky note with the number 1 on it.
  • ChangeArray - asks the universe to Reverse the array. The universe reverses the array and tells ChangeArray that the new array is in slot 2.
  • ChangeArray - crosses out the 1 on the sticky note and writes a 2.

In this case, the caller now has a new reference to the reversed array. Since the reference ("sticky note") was passed instead of the value (the number on the note), the caller sees any changes to that reference.

Now let's look at ChangeArrayElements:

  • Main - still has 1 on a sticky note labeled "weekDays"
  • Main - tells ChangeArrayElements that there is an array at slot 1.
  • ChangeArrayElements - writes down the number 1 on a sticky note labeled arr.
  • ChangeArrayElements - changes in the values in the first three buckets of the array in slot 1.

Note that the difference here is that the original array was modified. Since both the caller and function are looking at the same array, they both see the changes.

Upvotes: 2

Related Questions