Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Arrays by Value and by Reference

Tags:

arrays

c#

These are example from a c# book that I am reading just having a little trouble grasping what this example is actually doing would like an explanation to help me further understand what is happening here.

        //creates and initialzes firstArray
        int[] firstArray = { 1, 2, 3 };

        //Copy the reference in variable firstArray and assign it to firstarraycopy
        int[] firstArrayCopy = firstArray;

        Console.WriteLine("Test passing firstArray reference by value");


        Console.Write("\nContents of firstArray " +
            "Before calling FirstDouble:\n\t");

        //display contents of firstArray with forloop using counter
        for (int i = 0; i < firstArray.Length; i++)
            Console.Write("{0} ", firstArray[i]);

        //pass variable firstArray by value to FirstDouble
        FirstDouble(firstArray);

        Console.Write("\n\nContents of firstArray after " +
            "calling FirstDouble\n\t");

        //display contents of firstArray
        for (int i = 0; i < firstArray.Length; i++)
            Console.Write("{0} ", firstArray[i]); 

        // test whether reference was changed by FirstDouble
        if (firstArray == firstArrayCopy)
            Console.WriteLine(
                "\n\nThe references refer to the same array");
        else
            Console.WriteLine(
                "\n\nThe references refer to different arrays");

       //method firstdouble with a parameter array
       public static void FirstDouble(int[] array)
    {
        //double each elements value
        for (int i = 0; i < array.Length; i++)
            array[i] *= 2;

        //create new object and assign its reference to array
        array = new int[] { 11, 12, 13 };

Basically there is the code what I would like to know is that the book is saying if the array is passed by value than the original caller does not get modified by the method(from what i understand). So towards the end of method FirstDouble they try and assign local variable array to a new set of elements which fails and the new values of the original caller when displayed are 2,4,6.

Now my confusion is how did the for loop in method FirstDouble modify the original caller firstArray to 2,4,6 if it was passed by value. I thought the value should remain 1,2,3.

Thanks in advance

like image 305
Tim Avatar asked Apr 25 '12 23:04

Tim


People also ask

Are arrays passed by value or reference?

Longer answer: Like all Java objects, arrays are passed by value ... but the value is the reference to the array. So, when you assign something to a cell of the array in the called method, you will be assigning to the same array object that the caller sees. This is NOT pass-by-reference.

How do you pass an array by passing by reference?

How to pass an array by reference in C++ If we pass the address of an array while calling a function, then this is called function call by reference. The function declaration should have a pointer as a parameter to receive the passed address, when we pass an address as an argument.

Can we pass array by reference?

Arrays can be passed by reference OR by degrading to a pointer. For example, using char arr[1]; foo(char arr[]). , arr degrades to a pointer; while using char arr[1]; foo(char (&arr)[1]) , arr is passed as a reference. It's notable that the former form is often regarded as ill-formed since the dimension is lost.

Does C# pass arrays by reference or value?

Yes, they are passed by reference by default in C#. All objects in C# are, except for value types. To be a little bit more precise, they're passed "by reference by value"; that is, the value of the variable that you see in your methods is a reference to the original object passed.


3 Answers

The key to understanding this is to know the difference between a value type and a reference type.

For example, consider a typical value type, int.

int a = 1;
int b = a;
a++;

After this code has executed, a has the value 2, and b has the value 1. Because int is a value type, b = a takes a copy of the value of a.

Now consider a class:

MyClass a = new MyClass();
a.MyProperty = 1;
MyClass b = a;
a.MyProperty = 2;

Because classes are reference types, b = a merely assigns the reference rather than the value. So b and a both refer to the same object. Hence, after a.MyProperty = 2 executes, b.MyProperty == 2 since a and b refer to the same object.


Considering the code in your question, an array is a reference type and so for this function:

public static void FirstDouble(int[] array)

the variable array is actually a reference, because int[] is a reference type. So array is a reference that is passed by value.

Thus, modifications made to array inside the function are actually applied to the int[] object to which array refers. And so those modifications are visible to all references that refer to that same object. And that includes the reference that the caller holds.

Now, if we look at the implementation of this function:

public static void FirstDouble(int[] array)
{
    //double each elements value
    for (int i = 0; i < array.Length; i++)
        array[i] *= 2;

    //create new object and assign its reference to array
    array = new int[] { 11, 12, 13 };
}

there is one further complication. The for loop simply doubles each element of the int[] that is passed to the function. That's the modification that the caller sees. The second part is the assignment of a new int[] object to the local variable array. This is not visible to the caller because all it does is to change the target of the reference array. And since the reference array is passed by value, the caller does not see that new object.

If the function had been declared like this:

public static void FirstDouble(ref int[] array)

then the reference array would have been passed by reference and the caller would see the newly created object { 11, 12, 13 } when the function returned.

like image 178
David Heffernan Avatar answered Oct 06 '22 11:10

David Heffernan


What a confusing use of terms!

To clarify,

  1. for a method foo(int[] myArray), "passing a reference (object) by value" actually means "passing a copy of the object's address (reference)". The value of this 'copy', ie. myArray, is initially the Address (reference) of the original object, meaning it points to the original object. Hence, any change to the content pointed to by myArray will affect the content of the original object.

    However, since the 'value' of myArray itself is a copy, any change to this 'value' will not affect the original object nor its contents.

  2. for a method foo(ref int[] refArray), "passing a reference (object) by reference" means "passing the object's address (reference) itself (not a copy)". That means refArray is actually the original address of the object itself, not a copy. Hence, any change to the 'value' of refArray, or the content pointed to by refArray is a direct change on the original object itself.

like image 17
user1570129 Avatar answered Oct 06 '22 12:10

user1570129


All method parameters are passed by value unless you specifically see ref or out.

Arrays are reference types. This means that you're passing a reference by value.

The reference itself is only changed when you assign a new array to it, which is why those assignments aren't reflected in the caller. When you de-reference the object (the array here) and modify the underlying value you aren't changing the variable, just what it points to. This change will be "seen" by the caller as well, even though the variable (i.e. what it points to) remains constant.

like image 7
Servy Avatar answered Oct 06 '22 10:10

Servy