“Call by value” vs “Call by reference” in C# (bis)

The previous example is good to get you going, there are however some side notes here to make. When a reference type is called by value, it is actually taking a shallow copy of the variable you pass into the method. Almost like you’re doing this:
variable inside the method  = variable outside the method
So you have 2 objects pointing to the same data, and so it is normal that when you’re adjusting the data inside the method it also applies to the data outside of the method, because it is the same data in memory. However, if inside of your method you reassign the method variable to a different object, a new object or null, the changes you then make after reassigning will no longer affect to variable outside of the method, because we are simply no longer referring to it.

And that is where the difference relies for calling by reference for reference types. The variable inside the method is not a copy of the variable passed into the method, it is the same variable which implies that if you assign it to null, a new object or another object inside the method these changes are also applied for the outer method variable. And to illustrate this: a code example.

In the previous example, add these functions:

private static void SetInitialData(List<int> numbers)
{

numbers = new List<int>();
numbers.Add(10);
numbers.Add(11);
numbers.Add(12);

}

private static void SetInitialData(ref List<int> numbers)
{

numbers = new List<int>();
numbers.Add(10);
numbers.Add(11);
numbers.Add(12);

}

And in the Main function, add these statements:

Console.WriteLine (“\nReset called by value…”);
SetInitialData(numbers);
for (int i=0; i<numbers.Count; i++) Console.WriteLine (“numbers[“ + i + “] = “ + numbers[i]);

Console.WriteLine (“\nReset called by reference…”);
SetInitialData(ref numbers);
for (int i=0; i<numbers.Count; i++) Console.WriteLine (“numbers[“ + i + “] = “ + numbers[i]);

We now get the following output:

k = 1
numbers[0] = 10
numbers[1] = 11
numbers[2] = 12

Increment called by value…
k = 1
numbers[0] = 11
numbers[1] = 12
numbers[2] = 13

Increment called by reference…
k = 2
numbers[0] = 12
numbers[1] = 13
numbers[2] = 14

Add called by value…
numbers[0] = 12
numbers[1] = 13
numbers[2] = 14
numbers[3] = 20

Add called by reference…
numbers[0] = 12
numbers[1] = 13
numbers[2] = 14
numbers[3] = 20
numbers[4] = 25

Reset called by value…
numbers[0] = 12
numbers[1] = 13
numbers[2] = 14
numbers[3] = 20
numbers[4] = 25

Reset called by reference…
numbers[0] = 10
numbers[1] = 11
numbers[2] = 12

As you can see, in the call by value method we reassigned the method variable and thus changes to this variable no longer applied to the variable passed into the method. In the call by reference method changes do apply because we’re basically working with the same variable.

Another thing to add here: variables of the type struct may look like a stripped down version of a class, it is however different in a way that a struct is a value type  while a class is a reference type. In coding a struct may look like a reference object of a class, however in behavior it  acts like primitive types like int, bool, … So if you pass a struct into a method and call it by value, the variable in the method is a copy of the struct passed into the method, and so if you change the struct variable in the method the changes will not apply to the struct outside of the method (unless you return the changes). When calling by reference, you’re working with the same variable as outside the method and so changes inside the method do also apply outside the method.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s