By Value vs. by Reference: Return Values for a Function
Dec 18, 2019 • 8 Minute Read
Introduction
In this guide, you will learn about the differences between returning values from functions by value and by reference using the C# programming language.
By the end of this guide, you will know:
-
The fundamental differences between a value type and a reference type
-
How to use a function that returns by value
-
How to use a function that returns by reference
By Value and By Reference
We will start with some background concepts, since they are important to know for the scope of this guide.
A function is a programming concept which allows you to package code in order to be reused at any time you would like. A function is intended to perform a task and can be called upon at will to perform that task. While creating a function, you have the option of passing values into its definition, known as parameters. Then, while calling your function, if it invokes parameters, you must supply arguments to pass into it. Arguments are values that you pass to a function to help perform the task of the function.
You can see an example that utilizes the concepts of a function, parameters, and arguments in the image below.
When passing values into your function, you can do so either by value or by reference. When you pass a value-type parameter to a function by value, it means that the changes you make to that parameter inside the function will only be affected while inside that function. There will be no effect on the original data that is stored in the argument value. In essence, when you pass by value, you are sending a copy of the variable into the function. The copied variable can get changed inside of the function; however, the value of the original data will remain preserved. A couple of examples of a value type are Enums and Structs.
On the other hand, when you pass a value-type parameter to a function by reference, the changes you make to that parameter inside the function will change the original data. When you pass by reference, you are passing the memory location of the variable to the function, and any changes you make inside a function will affect that location in memory and will therefore persist after the function completes. A couple of examples of reference types are Arrays and Delegates.
By Value In Depth
So what does a function that passes by value look like? We will use a similar approach as in the previous section with a function that performs multiplication. In the example below, we have declared an integer named x and assigned it a value of 5. We then pass x as an argument into the multiplyNumbersByVal function. In the multiplyNumbersByVal function, it accepts a parameter called y, and multiplies y by itself. There are three statements written to the console which show you the status of x before, while inside, and after going through the multiplyNumbersByVal function.
namespace Practice
{
class Program
{
public static void multiplyNumbersByVal(int y)
{
y *= y;
Console.WriteLine("Value of our variable inside multiplyNumbersByVal function: " + y);
}
public static void Main(string[] args)
{
int x = 5;
Console.WriteLine("Value of our variable before multiplyNumbersByVal function: " + x);
multiplyNumbersByVal(x);
Console.WriteLine("Value of our variable after multiplyNumbersByVal function: " + x);
}
}
}
When we execute this code, we get the following results. Observe how the value of our variable changed while inside the function but remained unchanged outside of the function. We have just passed a variable into a function by value.
By Reference In Depth
If you are looking to change the value of your variable while inside of a function, this is where we will pass a variable by reference. There are currently two ways to pass values by reference: by use of the ref keyword and the out keyword.
We will take a look at ref first, using the same concept as we did in the value type section. Looking at this example below, we have again declared an integer named x and assigned it a value of 5. We then pass x as an argument into the multiplyNumbersByRef function. In the multiplyNumbersByRef function, it accepts a parameter called y and multiplies y by itself. There are three statements written to the console which show you the status of x before, while inside, and after going through the multiplyNumbersByRef function.
namespace Practice
{
class Program
{
public static void multiplyNumbersByRef(ref int y)
{
y *= y;
Console.WriteLine("Value of our variable inside multiplyNumbersByRef function: " + y);
}
public static void Main(string[] args)
{
int x = 5;
Console.WriteLine("Value of our variable before multiplyNumbersByRef function: " + x);
multiplyNumbersByRef(ref x);
Console.WriteLine("Value of our variable after multiplyNumbersByRef function: " + x);
}
}
}
When we execute this code, we get the following results. Observe how the value of our variable changed while inside the function and then remained changed after the function. We have just passed a variable into a function by reference by use of the ref keyword.
The out keyword passes values by reference the same way the ref keyword does. The difference between the two is that using out does not require the variable to be initialized before it's passed into a function as an argument; rather, it needs to be initialized inside of the called function.
Because of this, the syntax is a bit different.
In the code block below, we will see a variable created but not initialized, then passed into a function by reference with use of the out keyword. Also notice that since we do not initialize our variable upon creation, we cannot print out the value before sending it to our function, so there are only two lines written to the console instead of three here.
namespace Practice
{
class Program
{
public static void multiplyNumbersByRef2(out int y)
{
y = 5;
y *= y;
Console.WriteLine("Value of our variable inside multiplyNumbersByRef2 function: " + y);
}
public static void Main(string[] args)
{
int x;
multiplyNumbersByRef2(out x);
Console.WriteLine("Value of our variable after multiplyNumbersByRef2 function: " + x);
}
}
}
As you can see, the results are the same, even though the syntax is a bit different.
Conclusion
This guide has addressed what it means to pass value-type variables by value and by reference and explained the difference between the two. We also went over examples of both types and looked at the output produced. -Knowing and understanding the differences between value types and reference types is a very important concept. It is important to know while writing code what values will be returned while writing a function, especially if you have clients using your software.
This is also an important concept to know if you are interviewing for a new job, as potential employers could ask you about this topic.
Possible interview questions to know:
- What is the difference between a value and reference type?
- What two keywords are associated with passing values by reference?
- Give some examples of value types and reference types.
I hope you have enjoyed reading this guide and that it will help you understand one of the most important concepts of the computer science field!