HomeSearch

C# Multiple Return Values

Return multiple values from a method. Use out and ref parameters and KeyValuePair.
Multiple return values. Methods return only one value. This value can be an object with multiple fields. Many options are available for returning multiple values from a method.ReturnOptimization
If you need to return multiple values, you can use out parameters or return a type instance containing all the values. We benchmark and compare methods that return multiple int values.
An example. There are 2 ways of returning multiple values using output parameters. We can use formal parameters modified by the out keyword.

Or: We can allocate a KeyValuePair instance to store the result values. A Tuple (or ValueTuple) can also be used.

Info: The first GetTwoNumbers() uses 2 output parameters. It assigns the storage locations (for the out parameters) in the method body.

Out

Next: The second GetTwoNumbers() returns a KeyValuePair generic struct instance instead of using output parameters.

KeyValuePairStruct

KeyValuePair: The two numbers are specified as the key and value of the struct. And this struct is returned.

C# program that uses multiple return values using System; using System.Collections.Generic; class Program { static void GetTwoNumbers(out int number1, out int number2) { number1 = (int)Math.Pow(2, 2); number2 = (int)Math.Pow(3, 2); } static KeyValuePair<int, int> GetTwoNumbers() { return new KeyValuePair<int, int>((int)Math.Pow(2, 2), (int)Math.Pow(3, 2)); } static void Main() { // Use out parameters for multiple return values. int value1; int value2; GetTwoNumbers(out value1, out value2); Console.WriteLine(value1); Console.WriteLine(value2); // Use struct for multiple return values. var pair = GetTwoNumbers(); Console.WriteLine(pair.Key); Console.WriteLine(pair.Value); } } Output 4 9 4 9
ValueTuple example. We can use a ValueTuple to return multiple values from a method. Consider this program. We must ensure the ValueTuple package is included before using it.ValueTupleTuple

Performance: The ValueTuple has excellent performance. When available, this type should be used—it is used in a similar way to Tuple.

C# program that uses ValueTuple using System; class Program { static (int, int) GetTwoNumbers() { // Return 2 numbers in a ValueTuple. return (10, 20); } static void Main() { var result = GetTwoNumbers(); Console.WriteLine(result.Item1); Console.WriteLine(result.Item2); } } Output 10 20
Performance. The first implementation, which uses out parameters, was found to be somewhat slower than the second, which uses the KeyValuePair.

Note: Inlining might account for why out parameters were slower. The compiler might not inline a method that uses out parameters.

Tip: The KeyValuePair is allocated on the stack, so it ends up being faster. The Tuple, meanwhile, is allocated on the heap.

Warning: This benchmark is based on a 32-bit Windows installation. It gives different results for a 64-bit version.

C# program that benchmarks multiple return values using System; using System.Collections.Generic; using System.Diagnostics; class Program { static void GetTwoNumbersA(out int number1, out int number2) { number1 = 1; number2 = 2; } static KeyValuePair<int, int> GetTwoNumbersB() { return new KeyValuePair<int, int>(1, 2); } static Tuple<int, int> GetTwoNumbersC() { return new Tuple<int, int>(1, 2); } static void Main() { const int max = 100000000; var s1 = Stopwatch.StartNew(); for (int i = 0; i < max; i++) { int a; int b; GetTwoNumbersA(out a, out b); if (a + b != 3) { throw new Exception(); } } s1.Stop(); var s2 = Stopwatch.StartNew(); for (int i = 0; i < max; i++) { var pair = GetTwoNumbersB(); int a = pair.Key; int b = pair.Value; if (a + b != 3) { throw new Exception(); } } s2.Stop(); var s3 = Stopwatch.StartNew(); for (int i = 0; i < max; i++) { var tuple = GetTwoNumbersC(); int a = tuple.Item1; int b = tuple.Item2; if (a + b != 3) { throw new Exception(); } } s3.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / max).ToString("0.00 ns")); Console.WriteLine(((double)(s3.Elapsed.TotalMilliseconds * 1000000) / max).ToString("0.00 ns")); Console.Read(); } } Output 1.64 ns, out 0.32 ns, KeyValuePair 5.40 ns, Tuple
A summary. Multiple values can be returned from a method invocation. We used out to pass parameters by deference. With KeyValuePair and Tuple we returned multiple values in a container.
© 2007-2019 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.
Home
Dot Net Perls