Edit: Updated to improve clarity (thanks to Paulo in the comments for helping to improve his article).
Tuples in C# are objects that can be created with a specific syntax. You don’t have to declare tuple types first like you do with classes for example, they can instead be created using a lightweight C# syntax.
A tuple is a object that holds a number of arbitrary data items and which has no custom behaviour. In contrast, a class or struct can have both data and custom behaviour.
For example the following creates a tuple with 2 string values:
(string, string) names = ("Sarah", "Smith");
Console.WriteLine($"First name: '{names.Item1}' Last name: '{names.Item2}'");
This code produces the output: First name: 'Sarah' Last name: 'Smith'
In the preceding code, the items inside the tuple don’t have names so they are referred to as Item1 and Item2 but you could also name the items, for example:
(string firstName, string lastName) names = ("Sarah", "Smith");
Console.WriteLine($"First name: '{names.firstName}' Last name: '{names.lastName}'");
If you had a rich Person class that had both data and behaviour, you could also add support for tuple-like deconstruction and unpackaging of a Person instance into variables just like you would do with a tuple instance.
Consider the following class:
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int AgeInYears { get; set; }
public string FavoriteColor { get; set; }
// methods etc.
}
We could create a tuple as before containing the first and last name as follows:
var sarah = new Person
{
FirstName = "Sarah",
LastName = "Smith",
AgeInYears = 42,
FavoriteColor = "red"
};
(string firstName, string lastName) names = (sarah.FirstName, sarah.LastName);
Console.WriteLine($"First name: '{names.firstName}' Last name: '{names.lastName}'");
This is however a little clunky, we can modify the Person class to provide support for a Person to have tuple-like deconstruction and unpacking semantics. To do this a public void method called Deconstruct can be added, for example:
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int AgeInYears { get; set; }
public string FavoriteColor { get; set; }
// methods etc.
public void Deconstruct(out string firstName, out string lastName)
{
firstName = FirstName;
lastName = LastName;
}
}
Now the code could be changed to:
var (firstName, lastName) = sarah;
Console.WriteLine($"First name: '{firstName}' Last name: '{lastName}'");
You could also add this deconstruction/unpackaging support to a class you can’t change by declaring an extension method such as:
static class PersonExtensions
{
public static void Deconstruct(this Person person, out string firstName, out string lastName)
{
firstName = person.FirstName;
lastName = person.LastName;
}
}
Or as another example, you could add tuple-like deconstruction & unpackaging support for the .NET String type:
static class StringExtensions
{
public static void Deconstruct(this string s, out string original, out string upper, out string lower, out int length)
{
original = s;
upper = s.ToUpperInvariant();
lower = s.ToLowerInvariant();
length = s.Length;
}
}
And then write:
var (original, upper, lower, length) = "The quick brown fox";
Console.WriteLine($"Original: {original}");
Console.WriteLine($"Uppercase: {upper}");
Console.WriteLine($"Lowercase: {lower}");
Console.WriteLine($"Length: {length}");
As Paulo points out in the comments there is no actual tuple instance per-se involved here, if look at the the decompiled source that Paulo links to you can see the Person has been unpackaged into multiple variables.
If you want to learn a load more C# tips check out my C# Tips and Traps course today. You can even currently start watching with a Pluralsight Free Trial with Unlimited Access
.


SHARE: