C# Tuple: Complete Guide
C# tuple is a lightweight data structure that provides concise syntax to group multiple data elements.
C# Tuples are a great way to pass multiple values around, but they can be hard to understand and use. How are values in a tuple related? How do you unbox a tuple into variables that have meaningful names?
If you are a web developer, this guide will help you use tuples in your own code right away!
We'll show you what c# tuples are, how they're implemented under the hood, and all of their various uses throughout every part of .NET development.
C# Tuples vs System.Tuple
Before we start, there's an important distinction to make:
The C# tuple type is not the same as the System.Tuple type.
C# tuples are backed by System.ValueTuple
types, while System.Tuple
type uses a class.
The System.ValueTuple types
differ from the System.Tuple
types in that:
- System.ValueTuple are structs, System.Tuple are classes,
- System.ValueTuple are mutable, System.Tuple are readonly
- System.ValueTuple members are fields, members of System.Tuple are properties.
Microsoft introduced C# tuples in C# 7. So if you are using C# 7 or later, use C# tuples based on System.ValueTuple
. But if you are using an older version, then you will have to use System.Tuple
.
In this guide, we cover both:
- C# Tuple
- System.Tuple
C# Tuple
A C# tuple is a comma-separated list of elements enclosed in parentheses. Tuples can contain 0 or more elements, including nested tuples.
A tuple has the following syntax:
(type1, type2,...)
For example, to represent a person's name and age we can use a tuple as follows:
(string firstName, int age)
C# tuple can hold any number of elements. But, the number of elements in a tuple must be fixed at compile time.
How to declare a tuple in C#?
The easiest way to create a tuple is to use parentheses syntax.
You can also create a tuple by specifying the type name, followed by the element types in parentheses. For example:
var latLong = (25.2, 12.2);
Console.WriteLine(latLong); // (25.2, 12.2)
How many elements can tuple hold?
C# tuple can contain any number of elements, from zero to an infinite number of elements. The name "tuple" might make you think the tuples contain two elements, but that's not the case.
Moreover, tuples can also contain other tuples as elements.
How to change C# tuple value?
In C#, tuples are mutable. They are implemented as ValueTuple which is a struct.
Tuples in C# can be updated in place by specifying new values for elements in the tuple. The following example shows how to update an existing tuple with new values:
var latLong = (25.2, 12.2);
latLong.Item1 = 42.8;
Console.WriteLine(latLong); // (42.8, 12.2)
Named Tuple
The default tuple member names is "Item1", "Item2", "Item3", etc. Default naming makes it difficult to keep track of the order of the tuple members.
C# 7 introduces a new type of tuple, called a "named tuple". Named tuples have named members, which makes them easier to read and write.
The following example shows how to create a named tuple:
(string ItemName, double Price) itemPrice = ("Socks", 12.99);
Console.WriteLine(itemPrice); // (Socks, 12.99)
Console.WriteLine(itemPrice.ItemName); // Socks
Console.WriteLine(itemPrice.Price); // 12.99
Tuple deconstruction
Tuple deconstruction is a feature for extracting the values from a tuple into individual variables.
The C# programming language has a special syntax for deconstructing tuples, which allows you to deconstruct all of the values in a tuple in one step. To deconstruct a tuple, use the same syntax as you would use to create a tuple.
In the example below, GetName
returns a string extracted from the (string, double)
tuple.
public static string GetName((string, double) itemPrice)
{
(string name, _) = itemPrice;
return name;
}
var itemPrice = ("Socks", 12.99);
Console.WriteLine(GetName(itemPrice)); // Socks
The underscore _
must be present because it indicates that we are ignoring the second parameter (price).
System.Tuple
System.Tuple is tuple implementation that uses classes. Prior C# 7, it was the only option. That's why it's still widely used.
System.Tuple type argument
Tuple classes require type arguments which you must provide when creating tuples using new
constructor. The type arguments determine the number and type of the tuple members. The type needs to match the tuple elements.
For example, the following code declares a tuple with two members of double
type:
Tuple<double, double> coordinates = new Tuple<double, double>(25.2, 12.2);
If you try to create a tuple without specifying the type of arguments, you'll get a compile error. For example:
Tuple<double, double> coordinates = new Tuple(25.2, 12.2);
Compilation error: Cannot create an instance of the static class 'System.Tuple'
Tuple.Create() vs new Tuple
C# has two methods for creating tuples: Tuple.Create() and new Tuple(). They both do the same thing, but Tuple.Create() is more concise and is preferred in most cases because it is easier to read and write.
var coordinates = Tuple.Create(25.2, 12.2); // preferred way
var coordinates = new Tuple<double, double>(25.2, 12.2); // less tidy variation
The fundamental difference between Tuple.Create and new Tuple is that you can use Tuple.Create without having to specify the type arguments. If you try to use new Tuple without specifying the type of arguments, you'll get a compile error.
Under the hood, both Tuple.Create() and new Tuple() do the same thing. Tuple.Create() calls the new Tuple() constructor with default values. The following example shows how both of these methods are translated to the same code:
public static class Tuple
{
public static Tuple<T1> Create<T1>(T1 item1) {
return new Tuple<T1>(item1);
}
}
How to access System.Tuple values?
To access the values in a tuple, you use the Item1, Item2, etc. notation. This is a shorthand for the members of the tuple.
Unlike C# tuples, System.Tuple's elements are not named, so you have to use ordinal index to access the value of tuple element.
var coordinates = Tuple.Create(25.2, 12.2);
double latitude = coordinates.Item1; // 25.2
double longitude = coordinates.Item2 // 12.2
How to change System.Tuple member values?
System.Tuple is immutable. They cannot be changed after they have been created.
var itemPrice = Tuple.Create("socks", 12.99);
itemPrice.Item2 = 8.99;
// Compilation error: Property or indexer 'Tuple<string, double>.Item2' cannot be assigned to -- it is read only
To change a tuple value, you have to replace the tuple you want to modify by a new tuple containing the updated value:
var itemPrice = Tuple.Create("socks", 12.99);
Tuple.Create(itemPrice.Item1, 8.99);
System.Tuple limitations
System.Tuple is limited to a maximum of 8 items. That's because it uses a class and the .NET Framework team had to provide a finite number of classes to represent it.
If we want to make a Tuple with more elements, we must first build nested Tuples.
The last element of an eight element tuple must be a Tuple.
var numbers = new Tuple<int, int, int, int, int, int, int, int>(1, 2, 3, 4, 5, 6, 7, 8);
/* Unhandled exception. System.ArgumentException: The last element of an eight element tuple must be a Tuple.
at System.Tuple`8..ctor(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest)
at Program.Main()
*/
The following code declares a tuple with eight members, where the last one is another tuple which satisfies the TRest
type constraint:
var numbers = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>>(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9, 10));
Console.WriteLine(numbers); // (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Console.WriteLine(numbers.Rest); // (8, 9, 10)
The nested tuple with 8 elements exposes the public Rest
property, which makes it easier to access the last tuple's members. To do so, Rest
uses internal ITupleInternal interface that allows to call tuple methods recursively without knowing the underlying types.
Tuple use cases
Tuples are great for moving data around without creating a custom class.
The most common use cases for tuples are:
- Return multiple values from a function without using the
out
parameter. - Grouping related values together.
- LIQN Projection - a LINQ technique for extracting a subset of elements from a sequence.
Code readability
Tuples are a very concise way of representing data, and they can be very helpful when you want to return multiple values from a method. However, they can also make your code more difficult to read. If you're not careful, it's easy to create tuples that are difficult to understand.
If the number of elements is over 3, it's better to use a class instead of a tuple. A class is more readable and it can be easier to add new members to a class than to a tuple.
Even though C# limits tuples to 7 elements, it's a good programming practice to create classes which group several values together if the number of elements is over 3. So you might never even hit the limit for tuples. But if you do, rethink your code. It's better to use a class.
ToString()
Tuples have a built-in ToString() method that returns a string representation of the tuple. The string contains the value of each member, separated by commas.
var coordinates = Tuple.Create(25.2, 12.2);
string description = coordinates.ToString(); // (25.2, 12.2)
Values get wrapped in parentheses.
With nested tuples, the string representation is indented to show the nesting.
Tuple Vs Dictionary
In C#, tuples are often used instead of Dictionary because they are more concise.
A Dictionary<TKey, TValue>
is a data structure that allows you to store key-value pairs. The key can be any type, and the value can be any type.
Dictionaries can only store one value per key, while tuples can have multiple values with the same key. That's why tuples are often used to instead of dictionaries.
Tuple Vs Enum
Tuples are often used in place of enums because C# doesn't support string enums.
For example, the following enum represents country names:
public enum Countries
{
UnitedStates = "US",
Canada = "CA"
}
But this code won't compile in C# because enums can only have numeric values.
A better solution is to use tuples:
List<(string CountryName, string CountryCode)> countries = new List<(string CountryName, string CountryCode)>() { ("UnitedStates", "US"), ("Canada", "CA") };
Console.WriteLine(countries[0].CountryCode); // US
Conclusion
In this article, we have explored how to use tuples in .NET development ecosystem. Tuples are a great way to return multiple values from a method, but they can also make your code harder to read. If you're not careful, it's easy to create tuples that are difficult to understand.
Different tuple implementations
It's important to understand the difference between the new C# 7 Tuples and System.Tuple
class.
The System.Tuple
class is a legacy implementation that is limited to a maximum of 8 items.
The new C# Tuple uses System.ValueTuple
under the hood.
This implementation is more versatile and has no limit on the number of elements.
Other differences between System.ValueTuple and System.Tuple include:
- System.ValueTuple is a struct.
- System.Tuple is a class.
- System.ValueTuple are mutable
- System.Tuple are read-only.
- Members of members of System ValuePair are fields, members of members of System Tuple are properties
When to use tuples
Tuples are a great way to group several pieces of information together, but they also make it hard to maintain your code. If you have a lot of items to store, use classes instead of tuples because they are easier to read and maintain.
If the number of items is less than 3, tuples are a good way to go.
Josip Miskovic is a software developer at Americaneagle.com. Josip has 10+ years in experience in developing web applications, mobile apps, and games.
Read more posts →- C# Tuples vs System.Tuple
- C# Tuple
- How to declare a tuple in C#?
- How many elements can tuple hold?
- How to change C# tuple value?
- Named Tuple
- Tuple deconstruction
- System.Tuple
- System.Tuple type argument
- Tuple.Create() vs new Tuple
- How to access System.Tuple values?
- How to change System.Tuple member values?
- System.Tuple limitations
- Tuple use cases
- Code readability
- ToString()
- Tuple Vs Dictionary
- Tuple Vs Enum
- Conclusion
- Different tuple implementations
- When to use tuples
I've used these principles to increase my earnings by 63% in two years. So can you.
Dive into my 7 actionable steps to elevate your career.