Working with Tuples - getting started
I have come across many instances where I wanted to return more than one value from a method. As Mads Torgersen pointed out, the existing options available to developers are not optimal. C# 7.0 has, therefore, introduced Tuple types and Tuple literals to allow developers an easy way of returning multiple values from methods. Developers can also rest easy when creating Tuples. Tuples are structs, which are value types. This means that they are created locally and are passed by copying the contents. Tuples are also mutable and Tuple elements are public mutable fields. I am personally very excited about using Tuples. Let's explore Tuples in closer detail in the following recipe.
Getting ready
Start off by creating a regular console application in Visual Studio 2017. Simply call the project you create cookbook
. Before I can jump into using Tuples in C# 7.0, I need to add in a NuGet package. Bear in mind that I am using the release candidate of Visual Studio. This process might change between now and the final release of the product.
- To do this, head on over to
Tools
,NuGet Package Manager
and then, click onManage NuGet Packages for Solution...
.

- Select the
Browse
tab and type inValueTuple
in the search box. TheSystem.ValueTuple by Microsoft
NuGet package should be displayed. Select thecookbook
project underManage Packages for Solution
and click on theInstall
button.
Note
Take note that I am using Visual Studio 2017 RC while writing portions of this book. You probably will not need to add System.ValueTuple
from NuGet some time in the future after the final release. Adding System.ValueTuple
from NuGet might, however, remain a requirement. Only time will tell.

- Visual Studio will now show you a prompt to review the changes you are about to make to your project. Just click on the
OK
button. Lastly, you will need to provide theLicense Agreement
required by Microsoft. Just click on theI Accept
button. Visual Studio will now start the NuGet package installation. It will show you its progress in theOutput
window.

After all this is complete, my Visual Studio solution looks as follows:

You will now be ready to create your first method that works with Tuples. Let's see how to do that next.
How to do it...
- Start off by creating a new class in the
Program.cs
file of your Visual Studio console application. You can call your class anything, but for the purposes of this book I will simply be calling my classChapter1
. Your code should now look as follows:
namespace cookbook { class Program { static void Main(string[] args) { } } public class Chapter1 { } }
- This is the format we will be using throughout this chapter. Let's assume that we want to write a method that needs to calculate the average score for a variable number of students. No grade has the same number of students in each class. Therefore, we want our method to return the number of students in the class for the calculated average score. Change the
static void main
method to contain a list of scores. We are also creating a new instance of theChapter1
class and calling the methodGetAverageAndCount()
, which will be used to return the two values we need.
Note
I will be hardcoding this for illustration purposes; in reality, though these scores can be for any number of students. Be sure to add the values exactly as I have in the code listing as I will be illustrating a final gotcha at the end of this recipe.
static void Main(string[] args) { int[] scores = { 17, 46, 39, 62, 81, 79, 52, 24 }; Chapter1 ch1 = new Chapter1(); var s = ch1.GetAverageAndCount(scores); }
- It is here that we can use the power of Tuples to declare the
GetAverageAndCount()
method in theChapter1
class. It accepts an array of integer scores and looks as follows:
public (int, int) GetAverageAndCount(int[] scores) { }
- Pay close attention to the return Tuple type
(int, int)
. We are only returning two values from theGetAverageAndCount()
method, but in reality you can return several values if needed. In order to run your code sample, we will create a dummy implementation of this method. To do this, just include a Tuple literal that returns two zeros.
public (int, int) GetAverageAndCount(int[] scores) { var returnTuple = (0, 0); return returnTuple; }
- Go back to the
static void Main
method where the Tuple returning method is called and write code to consume the return values. Every Tuple you create will expose members calledItem1
,Item2
,Item3
, and so on. These are used to get the values returned from a Tuple returning method.
static void Main(string[] args) { int[] scores = { 17, 46, 39, 62, 81, 79, 52, 24 }; Chapter1 ch1 = new Chapter1(); var s = ch1.GetAverageAndCount(scores); WriteLine($"Average was {s.Item1} across {s.Item2} students"); ReadLine(); }
- Be sure to add the following
using
the directive before the namespace.
using static System.Console;
- You will notice that we used
s.Item1
ands.Item2
to reference the return values returned from ourGetAverageAndCount()
method. While this is totally legal, it isn't very descriptive and makes it difficult to infer the usage of the variable returned. It basically means that you would have to remember thatItem1
is the average value andItem2
is the count value. Perhaps, it is the other way around? IsItem1
the count andItem2
the average? It really depends on what you are doing inside theGetAverageAndCount()
method (which can change over time). Our Tuple returning method can therefore be enhanced as follows:
public (int average, int studentCount) GetAverageAndCount(int[] scores) { var returnTuple = (0, 0); return returnTuple; }
- The Tuple return type can now declare variable names for its elements. This makes it easy for the caller of the
GetAverageAndCount()
method to know which value is which. You can still keep on usings.Item1
ands.Item2
, but it is now much easier to change the calling code in thestatic void Main
method accordingly:
static void Main(string[] args) { int[] scores = { 17, 46, 39, 62, 81, 79, 52, 24 }; Chapter1 ch1 = new Chapter1(); var s = ch1.GetAverageAndCount(scores); WriteLine($"Average was {s.average} across { s.studentCount} students"); ReadLine(); }
- Changing the interpolated string in
WriteLine
, we see that the usage of the values returned by the Tuple is much clearer. You now know that the first value is the average and that the second value is the count of the students used to calculate the average. Tuples, however, allow developers more flexibility. Remember the Tuple literal in theGetAverageAndCount()
method? We simply added this in the dummy implementation as follows:
var returnTuple = (0, 0);
- C# 7.0 also allows developers to add names to Tuple literals. Inside the
GetAverageAndCount()
method, change your Tuple literal as follows:
var returnTuple = (ave:0, sCount:0);
- I have just named the first value a name of
ave
(for average) and the secondsCount
(for student count). This is some really exciting stuff! After you have modified your Tuple literal, your dummy implementation of theGetAverageAndCount()
method should look as follows:
public (int average, int studentCount) GetAverageAndCount(int[] scores) { var returnTuple = (ave:0, sCount:0); return returnTuple; }
Note
Tuples play really nicely together. As long as the Tuple types match up, you do not have to worry that the ave
and sCount
names in the Tuple literal don't match the average
and studentCount
names of the return type.
How it works...
So far in this recipe, we have seen that Tuples give developers a lot of flexibility when you need to return several values from a method. While the dummy implementation of GetAverageAndCount()
simply returns the zero-valued Tuple literal, it gives you some idea how Tuples are wired up. This recipe is the foundation for the next recipe. I encourage you to go through both recipes thoroughly in order to gain the full benefit from understanding Tuples and how to use them.