C# - 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.
ValueTuple<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 per = (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.
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();