Before Tuples, I used to create a class
and its variables then create object from this class and make that object the return type for some functions.
Now with the tuples I can do the same and in c# 7.0 we can assign understandable names for tuples properties (before this it was item1
, item2
, etc..)
So now I am wondering, when should I use tuples and when should I create a class in c# 7.0?
I think this is going to become a question that gets asked a lot. There's currently no "best practice" for when to use the new value tuples vs a class.
However, it's worth reading what came up during previous conversations about the previous versions of tuples vs a class.
In my opinion the value tuple should only be used minimally and with no more than a maximum of three values. I think this strikes a good balance of "returning some values without the need for a class" and "horrific mess of values". If you have more than three values to return, make a class.
I'd also never use a tuple to return from a public facing API that consumers will have to use. Again, just use a class.
Here's some real world code that I've used:
As soon as I want to return more complex data, I make a class.
I want to start by mentioning that C# already had support for anonymous types. Which are reference types. Thus, you already had a suitable alternative to creating a named class.
One advantage of a named class is the will be easier to reuse (for example if you need the same type in multiple places) and document. Since the anonymous type is anonymous, you can only get variables typed to it if you can use
var
, which limits the contexts in which anonymous types are useful (for example, you can't use them as field types, return types or parameter types).Of course, you could go over some of the limitations of anonymous types by using
System.Tuple
. Which is also a reference type, and you can use it explicitly. The downside is that it lacks custom names for the members.C# 7 tuples (
ValueTuple
) can be considered similar to anonymous types. The first difference is that they are value types. This means that these tuples will have performance advantage as long as they stay in local scope or are moving across the stack (which is the common usage of anonymous types, due to its limitation).The second difference is that the new syntax allows tuples to appear in more places than anonymous types, as you know, you have syntactic sugar to define the return type to
ValueTuple
(while using anonymous types you had to returnobject
).The third difference is that
ValueTuple
supports deconstruction out of the box. To quote What’s New in C# 7.0:Which you can also do with custom types by adding a Deconstruct method.
For abstract:
ValueTuple
has syntactic sugar in C# 7.0, which should be considered for readability.ValueTuple
is a value type. All pros and cons between the use of aclass
and astruct
apply.ValueTuple
can used explictly (with or without the syntactic sugar) allowing it to have the versatility ofSystem.Tuple
while retaining named members.ValueTuple
supports deconstruction.Given that must of it is syntactic sugar, I would say that the stronger argument to choose
ValueTuple
is the same argument to choose astruct
. Which would be ideal for small, immutable types, that live mostly on the stack (so you do not have lots of boxing and unboxing).Comparing
ValueTuple
against a full blown struct, considering the syntactic sugar, I would suggest to useValueTuple
by default, unless you need an explicit layout or you need to add methods to it.I also want to say that the syntactic sugar does not necessarily improve readability. The main reason being that you are not naming the type, and the name of the type provides meaning to the code. In addition of that, you can add documentation to a
struct
orclass
declaration that eases understanding.All in all, the situation where
ValueTuple
really shines is returning multiple values from a method. In this case removing the need of creating newout
parameters. And the documentation of theValueTuple
used can live in the documentation of the method. If you find you need to do something else with theValueTuple
(defining extension methods for example), I would suggest to consider creating a named type instead.Tuples are intended to represent multiple values, like when a method intends to return multiple values. The tuple support in C# 7 uses
System.ValueTuple<...>
instances to represent that set of values. The names of those values are valid only in the context where they are being used and are not enforced.Classes are intended to represent a single value with several attributes.
Tuple is a great option when you want to combine multiple values (can be different types) into one object without creating a custom class. In this case, Tuple would be a fast and a perfect option to go with.
Generally you want to have a class when your object is going to be used somewhere else or if it represents a real object or a concept in your domain. You're probably going to create a class to represent a car or a car store, not tuples.
On the other hand, sometimes you just want to return a couple of objects from a method. Maybe they don't represent anything special, it's just that you need to return them together in that particular method. Sometimes, even if they do represent a concept from your domain (say you're returning
(Car, Store)
, which could be represented as aSale
object), you're not actually going to use them anywhere -- you're just moving data. In those cases, it's fine to use tuples.Now, speaking about C# specifically, there's one more thing you should know. C# 7's tuple type is actually the
ValueTuple
, which is a struct. Differently from classes, which are reference types, structs are value types. You can read more about that on msdn. Most importantly, know that they might involve a lot of copying, so be careful.Use a Class
If your objects are entities that are widely used throughout your application and are also stored in some kind of persistent storage like a relational database (SQL Server, MySQL, SQLite), a NoSQL Database or Cache (Redis, Azure DocumentDB) or even on simple text files or CSVs.
So yeah, anything persistent should have its own class.
Use a Tuple
If your objects are short lived without a special meaning for your application. For example, if you need to quickly return a pair of coordinates it's better to have something like this:
than define a separate class
A Tuple will save you time from having to allocate memory on the heap using
new
for such a simple operation.Another time when I find tuples useful is when performing multiple mathematical operations on some operands
It doesn't make sense to define a class in this case. No matter what the calculations are the results do not belong to a class. So the alternative would be to use
out
variables but I believe tuples are more expressive and result in improved readability.