Skip to content
Theory · Methods · lesson 4 of 8

Passing by value

Our copier has one more quirk. It never touches your sheets: before it starts, it makes an exact copy of them and works on the copy. Whatever it does to the copy, your sheets stay untouched on the glass.

A method in C# behaves the same way. Let's see what happens when a method changes its parameter:

C#
int x = 5;
AddTen(x);            // 15
Console.WriteLine(x); // 5

void AddTen(int n)
{
    n = n + 10;
    Console.WriteLine(n);
}

A copy on every call

Let's walk through the example line by line:

  1. int x = 5; creates the variable x.
  2. On the call AddTen(x), C# copies the value of x into the parameter n: now n is 5.
  3. n = n + 10 changes the copy: n becomes 15, and the method prints 15.
  4. The method ends, and n is gone. Console.WriteLine(x) prints 5: nobody touched the variable x.

A method gets a copy of the argument's value, not the variable itself. This is called passing by value, and it is what C# does by default.

For the types int, double, bool and char, the copy is fully independent of the original. These are value types: their variable holds the value itself, and that value is what a call copies.

Interviewers often ask this: "How does C# pass arguments to a method?" The answer has two parts:

  • by value by default: the method gets a copy, and assigning to the parameter does not change the caller's variable;
  • passing the variable itself is possible too, but you have to say so explicitly in both the method's declaration and the call.

A parameter is a separate variable

A parameter is an ordinary variable of the method:

  • you can read and change it like any other;
  • it is created on every call and disappears when the method ends;
  • it has no link to the caller's variable.

There are two cases where a link only seems to exist.

An expression as the argument

An argument can be an expression, not only a variable. On the call AddTen(x + 1), C# first computes 6 and copies that number into n. The method sees only the number and does not know where it came from.

The same name

The same name does not link anything either. If you name the parameter x, like the variable outside, there are still two variables. Inside the method the name x means the parameter, and assigning to it leaves the outer x alone.

Returning a new value

The methods in this lesson are linked to the calling code by two paths:

  • the arguments going in;
  • the result coming out.

For the calling code to get a new value, the method returns it with return. The calling code decides what to do with the result:

C#
int x = 5;
Console.WriteLine(PlusTen(x)); // 15
Console.WriteLine(x);          // 5
x = PlusTen(x);
Console.WriteLine(x);          // 15

int PlusTen(int n)
{
    return n + 10;
}

Let's go through the lines after int x = 5;:

  1. PlusTen(x) returns 15, and Console.WriteLine prints that number.
  2. The next line prints 5: the method returned a new value but did not change x.
  3. x = PlusTen(x) stores the result of the second call back in x.
  4. The last line prints 15: the variable changed only after the assignment.

The copier handed out the finished sheet, and you filed it in your own folder.

This is where the picture ends. A real copier needs paper and time for every copy, while C# copies the argument's value on every call, and for a number that takes no time at all.

Common mistake

The method returns a new value, but the result of the call was not stored anywhere:

C#
int x = 5;
PlusTen(x); // ✗
Console.WriteLine(x); // 5

The program compiles and prints 5. A method call can stand as a statement of its own even when the method returns a value, and then the result is lost. The compiler gives no warning about it, so store the result explicitly: x = PlusTen(x);.

Key points

  • A method gets a copy of the argument's value: assigning to the parameter does not change the caller's variable.
  • In C#, arguments are passed by value by default.
  • A method returns a new value with return, and the calling code stores it in a variable itself: x = PlusTen(x);.