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 deconstructing a Person instance into tuple elements.
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 be deconstructed into tuple elements. 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 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 support for deconstruction to 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}");
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 .