Using Tuples in C# to Initialize Properties in the Constructor and to Deconstruct Your Object
Recently I was asked by a developer what this code block here actually is:
public Friend(string firstName, string middleName, string lastName)
=> (FirstName, MiddleName, LastName) = (firstName, middleName, lastName);
This is actually a constructor that uses an expression body and tuples.
Since C# 7.0 you can use tuples in your code and you can also use expression bodied constructors. These two features allow you to write constructors in a more compact syntax that you see above. You see this syntax also quite often in code samples and also in the official .NET documentation.
Let’s look at it a bit more detailed. The traditional way to create a constructor and to initialize properties in a constructor looks like below:
public class Friend
{
public Friend(string firstName, string middleName, string lastName)
{
FirstName = firstName;
MiddleName = middleName;
LastName = lastName;
}
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
Since C# 7.0, you can use tuples in the constructor. The constructor below does this. It creates a tuple with the values of the three constructor parameters and assigns it to a tuple with the three properties. That means this constructor below does exactly the same as the constructor that you see in the code snippet above: It assigns the three parameter values to the three properties FirstName
, MiddleName
and LastName
:
public Friend(string firstName, string middleName, string lastName)
{
(FirstName, MiddleName, LastName) = (firstName, middleName, lastName);
}
Whenever you have a method, a property accessor, or a constructor with a single statement as the one above, it is a perfect fit to use an expression body. So, you can write the constructor like below, which is the syntax that you have seen at the beginning of this blog post:
public Friend(string firstName, string middleName, string lastName)
=> (FirstName, MiddleName, LastName) = (firstName, middleName, lastName);
Add a Deconstruct Method to Your Class
In the code snippet below I added a Deconstruct
method to the Friend
class. As you can see, it returns void
and it has the three out parameters firstName
, middleName
, and lastName
. In the method body it assigns the values of the properties FirstName
, MiddleName
, and LastName
to the three out parameters.
public class Friend
{
public Friend(string firstName, string middleName, string lastName)
=> (FirstName, MiddleName, LastName) = (firstName, middleName, lastName);
public void Deconstruct(out string firstName,
out string middleName,
out string lastName)
{
firstName = FirstName;
middleName = MiddleName;
lastName = LastName;
}
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
With that Deconstruct
method, you can deconstruct a Friend
object into a tuple as shown in the code snippet below.
var friend = new Friend("Thomas", "Claudius", "Huber");
var (first, middle, last) = friend; // This calls the Deconstruct method
Console.WriteLine(first); // Thomas
Console.WriteLine(middle); // Claudius
Console.WriteLine(last); // Huber
Now, when you look in the code snippet below at the body of the Deconstruct
method, you can see that it has three statements to set all the three out parameters. That’s a perfect use case for tuples.
public void Deconstruct(out string firstName,
out string middleName,
out string lastName)
{
firstName = FirstName;
middleName = MiddleName;
lastName = LastName;
}
The code snippet below shows how to use tuples in the Deconstruct
method. A tuple for the properties FirstName
, MiddleName
, and LastName
is created and assigned to a tuple with the out parameters firstName
, middleName
, and lastName
.
public void Deconstruct(out string firstName,
out string middleName,
out string lastName)
{
(firstName ,middleName,lastName) = (FirstName,MiddleName,LastName);
}
Now, with that single statement in the Deconstruct
method, you can also use an expression body like in the code snippet below.
public void Deconstruct(out string firstName,
out string middleName,
out string lastName)
=> (firstName, middleName, lastName) = (FirstName, MiddleName, LastName);
This leads to a more compact Friend
class that looks like below.
public class Friend
{
public Friend(string firstName, string middleName, string lastName)
=> (FirstName, MiddleName, LastName) = (firstName, middleName, lastName);
public void Deconstruct(out string firstName,
out string middleName,
out string lastName)
=> (firstName, middleName, lastName) = (FirstName, MiddleName, LastName);
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
Summary
As you’ve seen in this blog post, tuples are quite powerful to combine multiple assign statements into a single statement. And by combining tuples with expression bodies you get quite compact code that is still very readable for those who are familiar with tuples.
Happy coding,
Thomas
Comments (6)
In ihrem WPF buch, 5te Auflage, Seite 489, bei ICommand ist in dem Code Beispiel Leerzeichen Setzung der Properties kaputt.
Danke, eben nachgeschaut, stimmt. Hat beim Setzen wohl jemand die Leerzeichen aufgegessen. :) Ist allerdings immer noch gültiger C# Code, aber ja, unschön formatiert. Danke für den Hinweis.
Hello Thomas
I see that
public Friend(string firstName, string middleName, string lastName)
{
(FirstName, MiddleName, LastName) = (firstName, middleName, lastName);
}
turns into casual assignment
public Friend(string firstName, string middleName, string lastName)
{
string text2 = (FirstName = firstName);
text2 = (MiddleName = middleName);
text2 = (LastName = lastName);
}
on sharplab : https://tinyurl.com/assignmentTuple
This was super clear and informative! It’s not so often you read a technical article that is as well written as this one. Learned and enjoyed reading this, I appreciate your effort and hope you continue to create material for a long time!
Thank you Snoopy, glad you enjoyed it!
Thanks, C# 7+ Tuples makes more sense now :)