“Call by value” vs “Call by reference” in C#

In this small example I hope to show you the differences in passing reference and value types in C# and what happens if you make the parameters either call by value or call by reference. All combinations are possible.

Reference vs Value variable types
In C#, as you know there are different variable types, for example int’s are value types and List<in> and other objects are reference types. It means that a variable of type int contains a value that you can adjust directly in memory, while for reference variables the variable itself is more or less just a referring to a spot in memory where all the object data is located and so the reference variable itself actually only contains a memory address.

“Call by reference” vs “Call by value”
As you may or may not know there are also different ways of passing parameters in C#. You can either call them by value, which is the default way of doing so, but you can also call them by reference. To do this one needs to explicitly add ‘ref’ both in the method signature and when calling this method.
What is the difference? When you pass the parameters by value, a copy is being taken of the data. When using referenced parameters only the reference to the data is passed.
But what does this imply? Well.. when ‘calling by value’  you get a copy of the variable and whatever you do inside the method does not affect the variable outside of this method (unless you use a return statement and reassign the variable with the returning data). Yet, if you ‘call by reference’ you have a reference to the place in memory where the variable relies, and so when you’re changing the variable inside the method it will also affect the variable outside of the scope of the method.

There are however side affects that you need to know off… because reference type variables actually contain just a reference to a space in memory, the variable itself is always passed in a call by reference way, and so when passing reference types you do not explicitly have to do a call by reference, but it is happening implicitly.

Here is an example that shows the difference:

class MainClass
{

public static void Main (string[] args)
{

int k = 1; //value type
List<int> numbers = new List<int>(); //reference type
numbers.Add(10);
numbers.Add(11);
numbers.Add(12);

//print default values
Console.WriteLine (“k = “ + k);
for (int i=0; i<numbers.Count; i++) Console.WriteLine (“numbers[“ + i + “] = “ + numbers[i]);

Console.WriteLine (“\nIncrement called by value…”);
Increment(k); //value type, call by value
Increment(numbers); //reference type, call by value
Console.WriteLine (“k = “ + k);
for (int i=0; i<numbers.Count; i++) Console.WriteLine (“numbers[“ + i + “] = “ + numbers[i]);

Console.WriteLine (“\nIncrement called by reference…”);
Increment(ref k); //value type, call by reference
Increment(ref numbers); //reference type, call by reference
Console.WriteLine (“k = “ + k);
for (int i=0; i<numbers.Count; i++) Console.WriteLine (“numbers[“ + i + “] = “ + numbers[i]);

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

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

}

#region called by value
private static void Increment (int k)
{

k++;

}

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

for (int i=0; i<numbers.Count; i++) numbers[i]++;

}

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

numbers.Add(20);

}
#endregion

#region called by reference
private static void Increment (ref int k)
{

k++;

}

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

for (int i=0; i<numbers.Count; i++) numbers[i]++;

}

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

numbers.Add(20);

}
#endregion

}//end of class

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

As you can see, variable types called by value don’t get adjusted out of the method, only when you call them by reference. For reference types, there is no difference on first sight in between calling by value or calling by reference because the variable itself is already a reference.

Note: I’m testing this C# code on a Linux machine using MonoDevelop. On a Windows system using .Net you will however get the same results.

Advertisements

One thought on ““Call by value” vs “Call by reference” in C#

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