When to use: Tuple vs Class in C# 7.0
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 tuples, I can do the same thing, and in C# 7.0 we can assign understandable names for tuple properties (before this, it was item1
, item2
, etc..)
So now I am wondering, when do I use tuple and when do I create a class in C# 7.0?
As this answer is causing some confusion amongst some folk here, I should clarify that - as per the question - all references to "tuple" here refer to the ValueTuple
type and new tuple syntactic sugar features of C# 7 and in no way refer to the old System.Tuple
reference types.
So now I am wondering, when Should I use tuples and when Should I create a class in c# 7.0?
Only you can really answer that question as it really depends on your code.
However, there are guidelines and rules you can follow in guiding you in choosing between them:
Tuples are values, so are copied by value, rather than by reference.
Most of the time, this should not be an issue. However, if you are passing around tuples of large structs, this might have an impact on performance. Ref locals/returns can be used to work around these performance issues, though.
Additionally, because they are values, modifying a copy remotely will not change the original copy. This is a good thing, but could catch some folk out.
Tuple element names are not persisted
The names given to elements are used by the compiler and (in most cases) are not available at run-time. This means that reflection cannot be used to discover their names; they cannot be accessed dynamically and they cannot be used in razor views.
Also this is an important consideration with APIs. A tuple returned from a method is the exception to the rule regarding after-compilation name discoverability. The compiler adds attributes to the method that hold information on the tuple names. This means you can safely return a tuple from a public method in one assembly and access its names in another.
Tuples are lightweight
Tuples are much simpler to write than types as they are less verbose and the declaration can be "inlined" (ie declared at the point of use). This works well when declaring a method that returns multiple values, for example.
However, because they are declared at the point of use, if you have MethodA
that calls MethodB
that calls MethodC
and each returns a tuple, you'll need to redefine the tuple at every stage. There isn't (yet) a way of creating an alias of a tuple and re-using it across multiple methods.
Just use common sense
For any situation where you might consider using a tuple: simply ask yourself the question: "will a tuple simplify the code here". If the answer is "yes", then use one. And that ultimately is the primary consideration over whether to use a tuple or a custom class.
Generally speaking, named classes have some significance in the design of your system. They are also more verbose to write. For example, you may have a class called MediaFileOpener
. It is important to the design that we know what this class does - we are working with media files!
Anonymous types and tuples are used when there is no design significance and all you want is a lightweight Data Transfer Object (DTO) to move information around.
As rule, if your class requires some documentation to describe what it is for, or if there is behaviour that it provides, use a full class. If all you need is temporary storage or some sort of grouping, use a Tuple. Consider a situation where you want to return more than one value from an async method. Tuple is designed to solve that problem.
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:
(double Latitude, double Longitude) getCoordinates()
{
return (144.93525, -98.356346);
}
than define a separate class
class Coordinates
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
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
(double Result1, double Result2, double Result3) performCalculations(int operand1, int operand 2)
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.
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 a Sale
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.