‘Stupid’ Question 14: What is a ’Tuple’ in C#, and what can we use it for?
What is a ’Tuple’ in C#, and what can we use it for?
So, I’ve heard about these ‘Tuple’ - but never used it or spent too much time thinking about them. I actually thought it was in the collection family, some sort of dictionary or list. But I decided today to take a few minutes and give it a good Google, and with that I present to you the answer:
Tuple is a generic static class that was added to C# 4 and it can hold any amount of elements, and they can be any type you want. To hold more than 8 elements you will need to nest tuple objects.
You can read the story behind the Tuple here
After spending some time on SO and MSDN and various sites I found the following use-cases:
- Passing multiple values to a method that only accepts a single parameter.
- Return multiple values from a method – but don’t want to define a class (this example was the most popular one)
- Represent a single set of data (a lot of debate around this one)
Generally I got the impression that Tuple gets overused for convenience sake, and that tuples are more useful in functional languages such as F# ( which seems to be the driving force behind the creation of the Tuple in C#).
Hmm… honestly ,- my first impression was ‘Nice! How convenient!’ – But then I tried to use it and the code just stared back at me, it looked ugly. You know what I mean, when you just get the gut feeling that it doesn’t look/seem right. It seemed bulky and bloated. So I removed it. It might come in handy one day, but today wasn’t the day.
Comments
Until C# 5, probably the best use for System.Tuple was interop with F#, where tuples are the only way of returning more than one arbitrary value from a method. But with C# 5, the new async/await syntax, and the general emphasis on asynchronous operations, tuples have increased in usefulness. You can't have out or ref parameters in an async method, which means if you are returning multiple values, you need to group them together. That's where a Tuple type comes in handy, because it means you don't have to define a class just to wrap the return values. Example: C# 4, non-async: public bool TryGetCountOfSomething(Func predicate, out int count); C# 5, async: public async Task<Tuple> TryGetCountOfSomethingAsync(Func predicate); Sadly, in C# 5, we didn't get language support for "tuple destructuring", where the values of a tuple can be assigned to multiple variables in a single statement. When that comes (I'm assured it is; maybe in C# 6), you'll be able to call the above method like this: var success, count = await TryGetCountOfSomethingAsync(myPredicate); Until then, we have the inconvenience of referring to the values as Item1, Item2...
Bother. HTML-stripping appears to have spoiled my Tuple. That should have been Tuple, of course.
Tuple<bool, int>
seems useless, it looks like a map, i think that in some point C#, i think, that in some point has been added a lot of stuff to C# language, i liked until the version 2.5, nice blog btw
Note that while the Tuple class is static - it is basically a class factory for the templated classes like Tuple, Tuple, etc. I have not used Tuples too much myself, because I agree in many cases that's a bit lazy and I have not touched F# yet. Another use case I see might be if you want create some sort of library that needs to be flexible enough to work with these short fixed-length collections, of arbitrarily, but statically-typed variables. It might not be very common, but I can imagine algorithms that take such Tuples in and return them after performing some operation. An alternative for Tuples in the lazy-programmer cases are anonymous types: http://msdn.microsoft.com/en-us/library/bb397696.aspx
The thing about Tuples is that, in my opinion, they fit the need for internal code. When you're writing an API, it makes your code VERY hard to use.
I find the Tuple quite useless (when not used with F#). Most of the time I find myself implement my own KeyValuePair that has nicer Equal, GetHashCode, etc... methods.
Anyway... Much like all other generic types in .NET (e.g. Action, Func, etc) you are limited to 8 generic items within the tuple if you are not using nesting. If you want truly unlimited amount you can use anonymous classes and finally not abuse the "var" keyword.
Example:
var b = new {
item1 = 1,
item2 = 2,
item3 = 3,
item4 = 4,
item5 = 5,
item6 = 6,
item7 = 7,
item8 = 8,
item9 = 9,
item10 = 10,
item11 = "11"
};
Boris started to get to the point of Tuples. Start be considering why/where you'd want to use an anonymous type. (I like to use them for return sets from LINQ queries) The problem with anon types, is that you are limited in what you can do with them, notably, they can't be used as the return type of a method. To return an object like that, you'd have to give the class a name. But what the items being returned have no logical connection, other than being the two object needed to be returned. Say you had a webservice which returned a string, and you had a method which called that webservice. You'd need to return the string, but since the web request might fail, you'd need to also return a status code. You'd need a class which held both of those. Since they two items are connected, you'd probably name it something like GetWidgetStringWSReturnType and use it just for that function. But you'd probably soon want to use it for a different webservice method, and rename it to something like Return_Type_String_Int32. And that's fine until we have a webservice which returns a double, and we create Return_Type_Double_Int32. And then when we create Return_Type_Decimal_Int32, we decide to make it generic: Return_Type<T, U > But, while we are making it generic, we might decide we might use it for something Return types (we probably won't but let's pretend we will), and give it a different name, say "MultpleObjects<T, U> From there, we figure we'll probably one day want more than 2 definable objects in are MultipleObject class so we define MultpleObjects<T, U, V>, MultpleObjects<T, U, V, X> etc. Finally, we decide that "MultpleObjects" is too many syllables, and cut it down to just Tuple<T, U>.
Last modified on 2012-08-03