We all understand that functions in C# have a function signature, function body and a return type. The signature comprises the parameters sent to the function, the function body is the lines of code executed when the function is called and the return type is the type of value returned to the calling function. However, at times we need to return multiple values from a function to the calling method. This article explains various ways of doing that.
We can return multiple values from a function using the following 3 approaches:
- Reference parameters
- Output parameters
- Returning an Array
- Returning an object of class/struct type
- Returning a Tuple
Reference parameters
Reference parameters also known as “ref” parameters are one of the most common and oldest way of returning multiple values from a function. As the name suggests, they are passed as reference to the function and after the function executes, the updated value of the passed reference variable is returned back to the calling method. It is important to note that reference parameters must be defined, initialized and assigned before they are passed to function else you may encounter a compile time error. Reference parameters are defined in the function signature as –
public int MultipleReturns(int a, int b, ref int max) {
if (a < b) {
max = a;
return b;
} else {
max = b;
return a;
}
}
In the above snippet we have defined the function signature using 2 integer parameters a & b and a ref parameter max. The function returns the minimum value between a & B and also assigns the maximum value to the output parameter. You can call the function as below.
int a=10, b=20,max=0;
int min = MultipleReturns(a,b,ref max);
Console.WriteLine("Minimum Value: " + min);
Console.WriteLine("Maximum Value: " + max);
Cons of using ref parameters
- ref parameters do not work if you plan to use async/await functionality
- Not very friendly in terms of reading the code.
Output Parameters
Output parameters also known as “out” parameters and are similar to reference parameters. As the name suggests, they are passed to the function as parameters and the calling method expects some values to be passed back in the parameter from the function. Output parameters are defined in the function signature as
public int MultipleReturns(int a, int b, out int max) {
if (a < b) {
max = a;
return b;
} else {
max = b;
return a;
}
}
In the above snippet we have defined the function signature using 2 integer parameters a & b and an out parameter max. The function returns the minimum value between a & B and also assigns the maximum value to the output parameter. If the function MultipleReturns() does not set any value to max variable inside the body, a compile time error generates. Hence, it is mandatory to assign values to out parameters in the function body. This is also to be noted that you cannot define 2 functions with same signature but having difference of only ref & out parameters, else the compiler will throw an error. You can call the function as below –
int a=10, b=20,max=0;
int min = MultipleReturns(a,b,out max);
Console.WriteLine("Minimum Value: " + min);
Console.WriteLine("Maximum Value: " + max);
Cons of using out parameters
- out parameters do not work if you plan to use async/await functionality
- Not very friendly in terms of reading the code.
Returning Arrays
The third approach of returning multiple values from within a function is to return an array. Let us rewrite the MultipleReturns() function to return an array. The function will look as in the following:
public int[] MultipleReturns(int a, int b) {
int[] minMax = int[2];
if (a > b) {
minMax[0] = a;
minMax[1] = b;
} else {
minMax[0] = b;
minMax[1] = a;
}
return minMax;
}
If you notice in the preceding, we have declared an array inside the MultipleReturns() function and are returning that by assigning values to the 1st and 2nd index of the array as maximum and minimum values respectively. The preceding function will be called as in the following:
int a=10, b=20;
int []minMax = MultipleReturns(a,b);
Console.WriteLine("Minimum Value: " + minMax[1]);
Console.WriteLine("Maximum Value: " + minMax[0]);
Cons of returning arrays
- Arrays can be used when you need to return single type of data and can be very confusing if you return an array of type object
- There is no fixed definition on what value is stored at a given index of the array. Hence, chances of errors are high.
Returning an object of Class/Struct Type
Returning multiple values via arrays has a limitation wherein we can return multiple values of only the same type. For example, if we want to return a string as well as integer, it won't be possible using the 2nd approach. Returning an object of class/struct type is the most robust way of returning multiple values from a function. Here the function will return an object of a class/struct that can further encapsulate n number of properties within them. We'll be using a simple MinMax class to demonstrate this idea. Let us rewrite that function to return an object now:
struct MinMax
{
public int min;
public int max;
}
public MinMax MultipleReturns(int a, int b)
{
MinMax values = new MinMax();
values.min = a < b ? a : b;
values.max = a > b ? a : b;
return values;
}
You can call the function using the following code:
int a=10, b=20;
MinMax results = MultipleReturns(a,b);
Console.WriteLine("Minimum Value: " + results.min);
Console.WriteLine("Maximum Value: " + results.max);
Returning a Tuple
In simple words, a Tuple means “a data structure consisting of multiple parts”. Tuples were introduced in C# 4.0. In simple words, a Tuple can be defined as a single record of data having various data types. So, lets say we can have a Tuple having StudentName, StudentAge and StudentMarks without defining a class/struct. The example we’re using is not a perfect fit to explain tuples, but I will rewrite the same function to return a tuple for your understanding.
public Tuple<int,int> MultipleReturns(int a, int b)
{
int min, max;
if (a > b)
{
max = a;
min = b;
}
else
{
max = b;
min = a;
}
return new Tuple<int, int>(min, max);
}
In the code above, you notice that we have defined a function, calculated the minimum and maximum values and then returned a Tuple of type<int,int> back to the calling method. This lets the compiler know that a tuple having 2 integer values is being returned back. To call this function, we will write the below code.
int a=10, b=20;
var tuple = MultipleReturns(a,b);
Console.WriteLine("Minimum Value: " + tuple.Item1);
Console.WriteLine("Maximum Value: " + tuple.Item2);
Conclusion
After having a read on all the different approaches mentioned above, the usage completely depends on the project you’re working on and the exact requirements. Every approach has got its pros and cons but AFAIK performance wise, they are same.
I hope this article eliminates your concerns about how to return multiple values from within a function.
Keep learning and sharing.