C# 7.0 - Tuples To The Extreme!

Introduction

Tuples are something that many developers may not frequently work with on a day-to-day basis, but they have a few different uses. With the latest upcoming release of C# however, this may change as tuples are getting a major power-up and will likely see quite a bit more "play" in the real world.

What is a Tuple?

If we go by the MSDN description.

A tuple is a data structure that has a specific number and sequence of elements. An example of a tuple is a data structure with three elements (known as a 3-tuple or triple) that is used to store an identifier such as a person's name in the first element, a year in the second element, and the person's income for that year in the third element.

Or, more basically, you can think of it as a class without any actual properties or something that you might use if you are too lazy to create a class to implement some type of behavior.

Example. let's say you wanted to create a class to store a City / State combination that you might pass around.

public class Location
{
    // Properties to store city and state information
    public string City { get; set; }
    public string State { get; set; }
    // Constructor to initialize city and state
    public Location(string city, string state)
    {
        City = city;
        State = state;
    }
}
// Example usage
var location = new Location("Lake Charles", "LA");
// Print out the address using the properties of the Location class
var address = $"{location.City}, {location.State}";
// Alternatively, you can use Tuple for a concise representation
var locationTuple = new Tuple<string, string>("Lake Charles", "LA");
// Print out the address using Tuple's Item1 and Item2 properties
var addressTuple = $"{locationTuple.Item1}, {locationTuple.Item2}";

So, in some scenarios, especially quick and dirty ones, Tuple objects can be incredibly useful. MSDN also has a few common use cases that you might want to look over as well.

What's new with Tuples in C# 7.0?

Well, C# 7.0 introduces a feature that I know quite a few developers have been asking about for a while: multiple return values.

That's right; you can now write some code like the following without having to build a class, use a tuple, or a series of ref or out parameters.

public (string city, string state) GetCityAndState()
{
    // Return a tuple representing city and state information
    return ("Lake Charles", "Louisiana");
}

This would allow you to make a call to a single method and access each of the return values by their defined names as seen below.

public (string city, string state) GetCityAndState()
{
    // Return a tuple representing city and state information
    return ("Lake Charles", "Louisiana");
}

The results of these multiple return value methods can also be deconstructed in a variety of ways based on your needs.

// Using tuple deconstruction to get values from the function
(string city, string state) = GetCityAndState();
// Using var for type inference in tuple deconstruction
(var city, var state) = GetCityAndState();
// Using a single var declaration for multiple variables in tuple deconstruction
var (city, state) = GetCityAndState();
// Using existing variables in tuple deconstruction
(city, state) = GetCityAndState();

As you might imagine, initialization is going to take a similar syntactic approach roughly.

// Creating a tuple representing location information (city, state)
var location = ("Lake Charles", "Louisiana");

This is a feature that a few other popular programming languages like Python, Scala, Ruby, Go, and others have had for quite a while, so hopefully, it will be a nice addition to C#.

Cool. Anything else?

In addition to straightforward examples like those provided, these new ValueTuple objects can use things like type inference to match up the signature of the return type and ensure it is valid, like the following example.

public (string city, int population) FindBiggestCityWithPopulation(string state)
{
    // Create a tuple to store city and population information, initialized with default values
    var result = (city: "", population: 0);
    // Retrieve the biggest city in the specified state using _someService
    result.city = _someService.GetBiggestCity(state);
    // Get the population of the retrieved city
    result.population = _someService.GetPopulation(result.city);
    // Return the tuple containing city and population information
    return result;
}

Likewise, these new tuples also support the async/await pattern out of the box.

public async Task<(string bird, string flower)> GetStateBirdAndFlowerAsync(string state)
{
    // Retrieve the state bird asynchronously using _someService
    var bird = await _someService.GetStateBirdAsync(state);
    // Retrieve the state flower asynchronously using _someService
    var flower = await _someService.GetStateFlower(state);
    // Return a tuple containing state bird and flower information
    return (bird, flower);
}

How did this come to be?

One of the wonderful things about the "new" Microsoft development ecosystem is just how open it is. No longer are important development decisions made in dark, smoke-filled rooms but rather in transparent issues on GitHub.

If you want to take a look at the conversation that lead up to this feature, you can visit the proposal for multiple return values here. You may also want to consider looking around through the other active issues to see what other features might be coming soon.


Similar Articles