With the addition of the Tuple class in .net 4, I have been trying to decide if using them in my design is a bad choice or not. The way I see it, a Tuple can be a shortcut to writing a result class (I am sure there are other uses too).
So this:
public class ResultType
{
public string StringValue { get; set; }
public int IntValue { get; set; }
}
public ResultType GetAClassedValue()
{
//..Do Some Stuff
ResultType result = new ResultType { StringValue = "A String", IntValue = 2 };
return result;
}
Is equivalent to this:
public Tuple<string, int> GetATupledValue()
{
//...Do Some stuff
Tuple<string, int> result = new Tuple<string, int>("A String", 2);
return result;
}
So setting aside the possibility that I am missing the point of Tuples, is the example with a Tuple a bad design choice? To me it seems like less clutter, but not as self documenting and clean. Meaning that with the type ResultType
, it is very clear later on what each part of the class means but you have extra code to maintain. With the Tuple<string, int>
you will need to look up and figure out what each Item
represents, but you write and maintain less code.
Any experience you have had with this choice would be greatly appreciated.
Tuples are great if you control both creating and using them - you can maintain context, which is essential to understanding them.
On a public API, however, they are less effective. The consumer (not you) has to either guess or look up documentation, especially for things like
Tuple<int, int>
.I would use them for private/internal members, but use result classes for public/protected members.
This answer also has some info.
It depends, of course! As you said, a tuple can save you code and time when you want to group some items together for local consumption. You can also use them to create more generic processing algorithms than you can if you pass a concrete class around. I can't remember how many times I've wished I had something beyond KeyValuePair or a DataRow to quickly pass some date from one method to another.
On the other hand, it is quite possible to overdo it and pass around tuples where you can only guess what they contain. If you are going to use a tuple across classes, perhaps it would be better to create one concrete class.
Used in moderation of course, tuples can lead to more concise and readable code. You can look to C++, STL and Boost for examples of how Tuples are used in other languages but in the end, we will all have to experiment to find how they best fit in the .NET environment.
I've used tuples, both the
Tuple
and the newValueTuple
, in a number of different scenarios and arrived at the following conclusion: do not use.Every time, I encountered the following issues:
My opinion is tuples are a detriment, not a feature, of C#.
I have somewhat similar, but a lot less harsh, criticism of
Func<>
andAction<>
. Those are useful in many situations, especially the simpleAction
andFunc<type>
variants, but anything beyond that, I've found that creating a delegate type is more elegant, readable, maintainable, and gives you more features, likeref
/out
parameters.Similar to keyword
var
, it is intended as a convenience - but is as easily abused.In my most humble opinion, do not expose
Tuple
as a return class. Use it privately, if a service or component's data structure requires it, but return well-formed well-known classes from public methods.Tuples can be useful... but they can also be a pain later. If you have a method that returns
Tuple<int,string,string,int>
how do you know what those values are later. Were theyID, FirstName, LastName, Age
or were theyUnitNumber, Street, City, ZipCode
.Tuples are a useless framework feature in .NET 4. I think a great opportunity was missed with C# 4.0. I would have loved to have tuples with named members, so you could access the various fields of a tuple by name instead of Value1, Value2, etc...
It would have required a language (syntax) change, but it would have been very useful.