- Tuple
- ValueTuple
Tuple
The Tuple<T> class was introduced in .NET Framework 4.0. A tuple is a data structure that
contains a sequence of elements of different data types. It can be used where you want to have a data
structure to hold an object with properties, but you don't want to create a separate type for it.
Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>
The following example creates a tuple with three elements:
Tuple<int, string, string> person =new Tuple <int, string, string>(1, "Steve", "Jobs");
In the above example, we created an instance of the Tuple that holds a person's record. We
specified a type for each element and passed values to the constructor. Specifying the type of each element
is cumbersome. C# includes a static helper class Tuple, which returns an instance of the
Tuple<T> without specifying each element's type, as shown below.
var person = Tuple.Create(1, "Steve", "Jobs");
A tuple can only include a maximum of eight elements. It gives a compiler error when you try to include more than eight elements.
var numbers = Tuple.Create(1, 2, 3, 4, 5, 6, 7, 8);
Accessing Tuple Elements
A tuple elements can be accessed with Item<elementNumber> properties, e.g., Item1, Item2,
Item3, and so on up to Item7 property. The Item1 property returns the first element, Item2 returns the
second element, and so on. The last element (the 8th element) will be returned using the Rest
property.
var person = Tuple.Create(1, "Steve", "Jobs");
person.Item1; // returns 1
person.Item2; // returns "Steve"
person.Item3; // returns "Jobs"
var numbers = Tuple.Create("One", 2, 3, "Four", 5, "Six", 7, 8);
numbers.Item1; // returns "One"
numbers.Item2; // returns 2
numbers.Item3; // returns 3
numbers.Item4; // returns "Four"
numbers.Item5; // returns 5
numbers.Item6; // returns "Six"
numbers.Item7; // returns 7
numbers.Rest; // returns (8)
numbers.Rest.Item1; // returns 8
Generally, the 8th position is for the nested tuple, which you can access using the Rest
property.
Nested Tuples
If you want to include more than eight elements in a tuple, you can do that by nesting another tuple object
as the eighth element. The last nested tuple can be accessed using the Rest property. To access
the nested tuple's element, use the Rest.Item1.Item<elelementNumber> property.
var numbers = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9, 10, 11, 12, 13));
numbers.Item1; // returns 1
numbers.Item7; // returns 7
numbers.Rest.Item1; //returns (8, 9, 10, 11, 12, 13)
numbers.Rest.Item1.Item1; //returns 8
numbers.Rest.Item1.Item2; //returns 9
You can include the nested tuple object anywhere in the sequence. However, it is recommended to place the
nested tuple at the end of the sequence so that it can be accessed using the Rest property.
var numbers = Tuple.Create(1, 2, Tuple.Create(3, 4, 5, 6, 7, 8), 9, 10, 11, 12, 13 );
numbers.Item1; // returns 1
numbers.Item2; // returns 2
numbers.Item3; // returns (3, 4, 5, 6, 7, 8)
numbers.Item3.Item1; // returns 3
numbers.Item4; // returns 9
numbers.Rest.Item1; //returns 13
Tuple as a Method Parameter
A method can have a tuple as a parameter.
static void Main(string[] args)
{
var person = Tuple.Create(1, "Steve", "Jobs");
DisplayTuple(person);
}
static void DisplayTuple(Tuple<int,string,string> person)
{
Console.WriteLine($"Id = { person.Item1}");
Console.WriteLine($<span className="str">"First Name = { person.Item2}"</span>);
Console.WriteLine($<span className="str">"Last Name = { person.Item3}"</span>);
}
Tuple as a Return Type
A Tuple can be return from a method.
static void Main(string[] args)
{
var person = GetPerson();
}
static Tuple<int, string, string> GetPerson()
{
return Tuple.Create(1, "Bill", "Gates");
}
Usage of Tuple
Tuples can be used in the following scenarios:
- When you want to return multiple values from a method without using
reforoutparameters. - When you want to pass multiple values to a method through a single parameter.
- When you want to hold a database record or some values temporarily without creating a separate class.
Tuple Limitations:
- The
Tupleis a reference type and not a value type. It allocates on heap and could result in CPU intensive operations. - The
Tupleis limited to include eight elements. You need to use nested tuples if you need to store more elements. However, this may result in ambiguity. - The
Tupleelements can be accessed using properties with a name patternItem<elementNumber>, which does not make sense.
C# 7 includes ValueTuple to overcome Tuple's limitations and makes it even easier to work with Tuple.
ValueTuple
C# 7.0 (.NET Framework 4.7) introduced the ValueTuple structure, which is a value type
representation of the Tuple.
The ValueTuple is only available in .NET Framework 4.7. If you don't see ValueTuple in your project, then you need to install the ValueTuple. (.NET Framework 4.7 or higher, or .NET Standard Library 2.0 or higher already includes ValueTuple.)
To install the ValueTuple package, right-click on the project in the solution explorer and select Manage NuGet Packages... This will open the NuGet Package Manager. Click the Browse tab, search for ValueTuple in the search box, and select the System.ValueTuple package, as shown below.

ValueTuple Initialization
It is easy to create and initialize the ValueTuple. It can be created and initialized using
parentheses () and specifying the values in it.
var person = (1, "Bill", "Gates");
//equivalent Tuple
//var person = Tuple.Create(1, "Bill", "Gates");
The ValueTuple can also be initialized by specifying the type of each element, as shown below.
(int, string, string) person = (1, "Bill", "Gates");
person.Item1; // returns 1
person.Item2; // returns "Bill"
person.Item3; // returns "Gates"
The following is a short way of declaring types for each member.
(int, string, string) person = (1, "James", "Bond");
person.Item1; // returns 1
person.Item2; // returns "James"
person.Item3; // returns "Bond"
Note that we have not used var in the above tuple initialization statement; instead, we provided
the type of each member values inside the brackets.
Tuple requires at least two values. The following is NOT a tuple.
var number = (1); // int type, NOT a tuple
var numbers = (1,2); //valid tuple
Unlike Tuple, a ValueTuple can include more than eight values.
var numbers = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
Named Members
We can assign names to the ValueTuple properties instead of having the default property names
like Item1, Item2 and so on.
(int Id, string FirstName, string LastName) person = (1, "Bill", "Gates");
person.Id; // returns 1
person.FirstName; // returns "Bill"
person.LastName; // returns "Gates"
We can also assign member names on the right side with values, as below.
var person = (Id:1, FirstName:"Bill", LastName: "Gates");
Please note that we can provide member names either on the left or right sides but not on both sides. The left side has precedence over the right side. The following will ignore names on the right side.
// PersonId, FName, LName will be ignored.
(int Id, string FirstName, string LastName) person = (PersonId:1, FName:"Bill", LName: "Gates");
// PersonId, FirstName, LastName will be ignored. It will have the default names: Item1, Item2, Item3.
(string, string, int) person = (PersonId:1, FName:"Bill", LName: "Gates");
We can also assign variables as member values.
string firstName = "Bill", lastName = "Gates";
var person = (FirstName: firstName, LastName: lastName);
ValueTuple as Parameter
The ValueType can also be a parameter type or return type of a method. The following method accepts a
ValueTuple type parameter.
static void Main(string[] args)
{
DisplayTuple((1, "Bill", "Gates"));
}
static void DisplayTuple((int, string, string) person)
{
Console.WriteLine("{0}, {1}, {2}", person.Item1, person.Item2, person.Item3);
}
The following returns a ValueTuple from the method.
The following returns a ValueTuple from the method.
static void Main(string[] args)
{
var person = GetPerson();
Console.WriteLine("{0}, {1}, {2}", person.Item1, person.Item2, person.Item3);
}
static (int, string, string) GetPerson()
{
return (1, "Bill", "Gates");
}
You can also specify member names for a ValueTuple returned from the method.
static void Main(string[] args)
{
var person = GetPerson();
Console.WriteLine("{0}, {1}, {2}", person.Id, person.FirstName, person.LastName);
}
static (int Id, string FirstName, string LastName) GetPerson()
{
return (Id:1, FirstName: "Bill", LastName: "Gates");
}
Deconstruction
Individual members of a ValueTuple can be retrieved by deconstructing it. A deconstructing
declaration syntax splits a ValueTuple into its parts and assigns those parts individually to
fresh variables.
static void Main(string[] args)
{
// change property names
(int PersonId, string FName, string LName) = GetPerson();
}
static (int, string, string) GetPerson()
{
return (Id:1, FirstName: "Bill", LastName: "Gates");
}
We can also use var instead of explicit data type names.
static void Main(string[] args)
{
// use var as datatype
(var PersonId, var FName, var LName) = GetPerson();
}
static (int, string, string) GetPerson()
{
return (Id:1, FirstName: "Bill", LastName: "Gates");
}
ValueTuple also allows "discards" in deconstruction for the members you are not going to use.
// use discard _ for the unused member LName
(var id, var FName, _) = GetPerson();