C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
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.
OutNext: The second GetTwoNumbers() returns a KeyValuePair generic struct instance instead of using output parameters.
KeyValuePairStructKeyValuePair: 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
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
Version 1: This version of the code uses out parameters to return 2 values from a method.
Version 2: Here we use a KeyValuePair and read in its Key and Value properties from the returned method.
Version 3: A tuple can be used to return 2 values from a method. We access Item1 and Item2.
Result: The first implementation, which uses out parameters, was found to be somewhat slower than the second, which uses the KeyValuePair.
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();
// Version 1: use 2 out parameters.
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();
// Version 2: return KeyValuePair.
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();
// Version 3: return tuple.
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