C# 7 Makes Tuples Cool!
Updated: May 29, 2020
First things first: What the heck is a “Tuple”?
Tuples first came to C# in .NET 4.0 and provided a way to create an immutable group of objects without creating a new class or struct. It’s tempting to refer to a Tuple as a “collection of objects” but that would imply that each object is of the same type and Tuples allow you to mix different types. Tuples are immutable and even the order of each object in the Tuple class cannot be changed after the Tuple has been created.
Let’s use the standard example of a simple “Person” class:
If you wanted to pass some property values of a Person to another class, you would normally need to create an instance of the class then populate it with the values. Using an object initializer, it would look something like this:
And now you can pass “p1” or “p2” as a parameter to another class, or use them as a return value from your class. Nothing new here.
But what if all you really want to do is return two strings and an integer from a method, but you don’t want to create a whole new class to do so? Or what if you want to pass these multiple parameters to a BackgroundWorker that only accepts one argument? Using Tuples, these values could be represented without creating a new class like this:
You can still pass “p1” or “p2” as a parameter, and they still contain the types and values you want to pass, but you didn’t have to create a whole new class.
Why aren’t Tuples used more often? While the idea of an immutable group of objects without having to create a whole new class or struct sounds like it could be super helpful, the implementation of Tuples in C# made them a bit awkward to use. Some even consider the use of Tuples to be a “code smell” because there is no intuitive way to reference the contents of the Tuple so that it makes sense when looking at the code. In our above example, if we were returning the p1 or p2 Tuple object from a method, we could only refer to the values using p1.Item1, p1.Item2, and p1.Item3:
We can tell from intellisense that “Item1” and “Item2” are strings and that “Item3” is an integer, but that’s really all we know unless we look up the code where this Tuple is created and find out exactly what those values are supposed to represent. You may not even have access to the code that produced the Tuple in the first place, in which case it’s off to the documentation you go to look up the API and find out what exactly is “Item1” supposed to be. And nobody likes digging into documentation.
If Tuples are so awkward to use, why have them at all? Tuples are commonly used in functional programming languages, so when F# came to the .NET family they created their own implementation of a Tuple class and the Microsoft language team quickly started pushing to have Tuples added to the .NET Framework. So, the .NET team got together and came up with the requirements and added official Tuple support to the .NET 4.0 Framework.
I’m sure Tuples have gotten some use since then in C#, but they have not been very widely used and are rarely recommended for anything other than as temporary placeholders when refactoring existing code.
So what’s new with Tuples? In C# 7.0, there is a new feature that allows for multiple values to be returned from a single method. Using the same simple example from above, if we wanted to return a “FirstName”, “LastName” and “Age” from a method without returning an instance of the Person class we could do it like this:
And now when we call this method, we get back an instance of a Tuple and we can refer to the values inside the Tuple using meaningful names instead of “Item1” and “Item2”:
The returned value is essentially an anonymous type with named properties. This magic is made possible by giving the existing Tuple class an overhaul making them much less awkward to use. But if you just like to embrace the awkwardness, you can still use “Item1”, “Item2” and “Item3” too.
Keep this new feature in mind when you start using C# 7.0 and maybe you’ll find it useful.