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.
Leandro AzevedoPosted Mar 18, 2024, 9:46 PM
Good Article
Jason PerryPosted Jul 27, 2021, 1:56 PM
The first two code examples contain a logic error. If a is less than b... a is definitely not the max!
dnyaneshwar galavePosted May 25, 2021, 5:39 PM
One mistake in ref while making method ..there should be static method
Sarmad YousifPosted Jan 19, 2021, 4:14 PM
For Returning an object of Class/Struct Type, can we return values as a list after we call the function and do something like foreach(var item in values){}
Sujeet SinghPosted Jan 25, 2020, 4:08 PM
One of the new feature is now available is<br> public (bool, string) SomeMethod(int number1, int number2) { return (true, "blah blah blah"); }
SWAMY YTPosted Jun 21, 2019, 12:51 AM
Thanks for the article. welly explained
Suresh ParmarPosted Oct 26, 2017, 10:40 AM
Thank you so much.....:)
Vivek KumarPosted Apr 28, 2016, 3:24 PM
Good one
Jon GraefPosted Feb 26, 2016, 11:39 AM
Excellent! Was able to use my first Tuple thanks to this article.
Santhakumar MunuswamyPosted Jun 30, 2015, 2:48 PM
Good show
Vipul MalhotraPosted Jun 30, 2015, 11:08 AM
nice article..Thanks for writing
Chiheb ChebbiPosted Jun 29, 2015, 10:23 AM
keep it up thanks
Afzaal Ahmad ZeeshanPosted Jun 28, 2015, 3:50 PM
Good article, perhaps the arrays mechanism was in my mind.
Teddy KurianPosted Jun 26, 2015, 2:51 AM
Thanks
Rahul Kumar SaxenaPosted Jun 25, 2015, 4:22 AM
Good show
sreenivasa kPosted Jun 24, 2015, 2:04 PM
nice one
Pankaj Kumar ChoudharyPosted Jun 24, 2015, 10:49 AM
Good Information Sir............
Debasis SahaPosted Jun 24, 2015, 10:12 AM
Good Article
Former memberPosted Jun 24, 2015, 10:10 AM
Nice article
Nitesh KejriwalPosted Jun 24, 2015, 9:25 AM
Thanks Nilesh Jadav
Nilesh JadavPosted Jun 24, 2015, 9:18 AM
This is really nice one ! Thank you for sharing
Vipul MalhotraPosted Jun 24, 2015, 9:02 AM
Nice writing..
Santisantosh MahapatraPosted Jun 24, 2015, 4:27 AM
How about return Tuple.Create(s11, s12);
Gowtham RajamanickamPosted Jun 24, 2015, 4:17 AM
great nitesh....
Gaurav GuptaPosted Jun 24, 2015, 2:20 AM
Reference parameters must be Initilized or Assinged before passed, not just defined.
Nagaraj SPosted Jun 19, 2015, 10:44 AM
Very good explanation
Mohammad KhalidPosted Jun 18, 2015, 10:15 AM
Worth reading the article.. Very well explained ....
Jaipal ReddyPosted Jun 15, 2015, 8:12 AM
Nice explanation @Nitesh sir.
Vidya Vrat AgarwalPosted Jun 5, 2015, 3:43 PM
Well explained :)
Upendra Pratap ShahiPosted Jun 5, 2015, 6:58 AM
Nice explanation dear..
Khargesh RajputPosted Jun 5, 2015, 6:34 AM
thanks for sharing sir and helpful comments makes it better
Manoj KulkarniPosted Jun 5, 2015, 6:03 AM
Nice article. Thank you for sharing.
Kannan SudhakaranPosted Jun 5, 2015, 4:26 AM
Nice
NitinPosted Jun 5, 2015, 4:22 AM
nice
Amol SarkatePosted Jun 5, 2015, 3:00 AM
Nitesh sir , Thanks for giving valuable understandable Information
Dinesh BeniwalPosted Jun 4, 2015, 12:37 PM
Thanks for sharing Nitesh
Sibeesh VenuPosted Jun 4, 2015, 8:34 AM
Good one.
Danny SchneiderPosted Jun 4, 2015, 6:46 AM
I share the opinion of Micha Conrad and I often prefer generic Lists or Dictionaries to return all my needed data. But the decision, which way to choose is often determined by the structure of the data and the source from where the data comes. So I do not transform data when I query them from a database, instead I often use the "recordset" structures returned by queries. In other cases I use simple data classes, which come close to the given struct approach...
Michael ConradPosted Jun 4, 2015, 5:02 AM
Not bad for starters, but maybe highlight the dis/advantages of each method (while I see array to return multiple values not as a viable option at all). Maybe mention that using out parameters will not work if you plan to make use of async/await. Also, out parameter are sometimes not very friendly to read/understand the code. Returning an object is in 99% of the cases the best way in my humble opinion.
Santhakumar MunuswamyPosted Jun 3, 2015, 2:56 PM
Nice
Pankaj Kumar ChoudharyPosted Jun 3, 2015, 11:39 AM
Nice Article sir but it may more better.......
Sandeep Singh ShekhawatPosted Jun 3, 2015, 6:32 AM
You can add two more approaches in this article one is Tuple<T>(in T) and another is ref .
Akhil MittalPosted Jun 3, 2015, 4:15 AM
public int MultipleReturns(int a, int b, 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.
Akhil MittalPosted Jun 3, 2015, 4:15 AM
Bug : There should be out parameter defined in the function in your first code snippet,