95

I'm looking at the new C# feature of tuples. I'm curious, what problem was the tuple designed to solve?

What have you used tuples for in your apps?

Update

Thanks for the answers thus far, let me see if I have things straight in my mind. A good example of a tuple has been pointed out as coordinates. Does this look right?

var coords = Tuple.Create(geoLat,geoLong);

Then use the tuple like so:

var myLatlng = new google.maps.LatLng("+ coords.Item1 + ", "+ coords.Item2 + ");

Is that correct?

SteveC
  • 15,808
  • 23
  • 102
  • 173
Chaddeus
  • 13,134
  • 29
  • 104
  • 162
  • 3
    possible duplicate of [Is Using Tuples in my .NET 4.0 Code a Poor Design Decision?](http://stackoverflow.com/questions/3017352/is-using-tuples-in-my-net-4-0-code-a-poor-design-decision) – John Saunders Jun 22 '10 at 02:13
  • 4
    Well, I can think of two answers ... – Noon Silk Jun 22 '10 at 02:17
  • 13
    If the concept of "coordinate" makes sense as a class then I would make it a class. Use tuples for those situations where there is *not* some sensible "business logic" concept for the set of data that justifies making a type. – Eric Lippert Jun 22 '10 at 02:37
  • @Eric Lippert - good point, and that's what I've always done. Then I read about Tuples and was curious about what they're designed to solve. Thanks! – Chaddeus Jun 22 '10 at 04:15
  • 13
    Coordinates are not a good example of tuple. Tuple in C# is just an ad-hoc solution in cases when you have to return (from a function) two values. Instead of setting one result type plus one out parameter it is more elegant to return one tuple. This way you don't have to declare the second parameter in advance. The difference is even more clear in C++ (you can const the result, but you cannot const the out/ref parameter). – greenoldman Jun 22 '10 at 05:29
  • 8
    Because python had it, and python can't have anything that C# doesn't have ;) – Evan Plaice Jun 22 '10 at 07:03
  • 1
    possible duplicate of [Practical example where Tuple can be used in .Net 4.0?](http://stackoverflow.com/questions/2745426/practical-example-where-tuple-can-be-used-in-net-4-0) – nawfal Jun 04 '14 at 13:34

13 Answers13

116

When writing programs it is extremely common to want to logically group together a set of values which do not have sufficient commonality to justify making a class.

Many programming languages allow you to logically group together a set of otherwise unrelated values without creating a type in only one way:

void M(int foo, string bar, double blah)

Logically this is exactly the same as a method M that takes one argument which is a 3-tuple of int, string, double. But I hope you would not actually make:

class MArguments
{
   public int Foo { get; private set; } 
   ... etc

unless MArguments had some other meaning in the business logic.

The concept of "group together a bunch of otherwise unrelated data in some structure that is more lightweight than a class" is useful in many, many places, not just for formal parameter lists of methods. It's useful when a method has two things to return, or when you want to key a dictionary off of two data rather than one, and so on.

Languages like F# which support tuple types natively provide a great deal of flexibility to their users; they are an extremely useful set of data types. The BCL team decided to work with the F# team to standardize on one tuple type for the framework so that every language could benefit from them.

However, there is at this point no language support for tuples in C#. Tuples are just another data type like any other framework class; there's nothing special about them. We are considering adding better support for tuples in hypothetical future versions of C#. If anyone has any thoughts on what sort of features involving tuples you'd like to see, I'd be happy to pass them along to the design team. Realistic scenarios are more convincing than theoretical musings.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Excellent info. I still can't think of a good scenario to use tuples in my apps, but understand the concept better now. Thank you! – Chaddeus Jun 22 '10 at 04:17
  • Very interesting to see the beginning of language convergence between C# and F#. Might things like `Asynch.Parallel` turn up in hypothetical future versions of C#? – MalcomTucker Jun 22 '10 at 08:21
  • 1
    @MalcomTucker: Asychrony and parallelism are definitely on our minds as rich areas where language tools could be used to solve real problems. I don't think that F# style asynchronous workflows are necessarily the best fit for C#, but they definitely are inspiring. – Eric Lippert Jun 22 '10 at 12:19
  • 61
    While tuples are useful, one big drawback is clarity. It's hard to read and understand code that refers to `Item1`, `Item2`, etc... If tuples ever do achieve language support in C#, it would be wonderful to allow their members to be named (or at least aliased) in manner that allows code that uses them to be more understandable. In such a hypthetical future, I'd also love to see tuples of appropriate "shape" as legal params to methods that take individual parameters (and vice versa). So, `Tuple` can be passed to `M(int,string,bool)`. It would make memoizing methods much easier. – LBushkin Jun 22 '10 at 14:23
  • 3
    These "tuples" are basically all `public` access, _anonymous_ `struct` types with _unnamed members_. I would rather have the programmer write a `struct` with named members and return that, than have to deal with a `tuple` that does not tell me anything about the semantics of its members. – bobobobo May 10 '13 at 21:44
  • @bobobobo In a lot of cases where tuples are used (ie passing data asynchronously or just passing groups of values up/down the call stack) it would be a waste of effort and resources to add the additional structural overhead. – Evan Plaice Jun 24 '13 at 17:14
  • @LBushkin just when you start having that problem, you no more need *tuples*, but rather a *separate class*. it is a common error for every programming language — when one trying to write a data holder with a kind of tuples that their language supports just because it was faster to write, and next complains that it is hard to see which elements are what. – Hi-Angel Jun 03 '15 at 07:54
  • 1
    @Hi-Angel: The argument is not about quibbling over what counts as a tuple and what does not, but rather about *what is the set of features that modern line-of-business developers could use to increase their productivity*. LBushkin is expressing a feature request that the design team hears all the time: the desire to make a "record type" of some kind without the trouble and expense of making an entire class just to hold together a few fields. C# already has this feature for methods; it's called the "parameter list". – Eric Lippert Jun 03 '15 at 14:44
  • 2
    @Hi-Angel: You probably would not make the argument "if you want to access your method parameters by name then you should make a separate class" because that seems extremely heavy, but it only seems heavy because we're used to having the ability to instantly tie together a set of arbitrary variables with arbitrary types and names *when calling a method*. Imagine that no language had that feature; every method could only take a single argument, and if you wanted to pass two, you'd have to make a type and pass an instance of it. – Eric Lippert Jun 03 '15 at 14:47
  • Btw, here **is** that language — in Haskell every function takes a single argument. Though one won't easily notice that because a function of multiple arguments done with [carrying](http://en.wikipedia.org/wiki/Currying). – Hi-Angel Jun 03 '15 at 15:01
22

Tuples provide an immutable implementation of a collection

Aside from the common uses of tuples:

  • to group common values together without having to create a class
  • to return multiple values from a function/method
  • etc...

Immutable objects are inherently thread safe:

Immutable objects can be useful in multi-threaded applications. Multiple threads can act on data represented by immutable objects without concern of the data being changed by other threads. Immutable objects are therefore considered to be more thread-safe than mutable objects.

From "Immutable Object" on wikipedia

Evan Plaice
  • 13,944
  • 6
  • 76
  • 94
  • Thank you for adding additional info to the question. Much appreciated. – Chaddeus Jun 22 '10 at 07:19
  • If you want an immutable collection, you should use an immutable collection, not a Tuple. The difference is that for most immutable collections you don't to have to specify the number of elements at compile-time – BlueRaja - Danny Pflughoeft Apr 28 '14 at 21:00
  • @BlueRaja-DannyPflughoeft Back when I wrote this answer the C# immutable collection classes were still not available in the BCL. Guess I'll change 'collection' to 'object' since MS neutered the Tuple implementation in C# – Evan Plaice Apr 28 '14 at 21:59
12

It provides an alternative to ref or out if you have a method that needs to return multiple new objects as part of its response.

It also allows you to use a built-in type as a return type if all you need to do is mash-up two or three existing types, and you don't want to have to add a class/struct just for this combination. (Ever wish a function could return an anonymous type? This is a partial answer to that situation.)

Toby
  • 7,354
  • 3
  • 25
  • 26
10

It's often helpful to have a "pair" type, just used in quick situations (like returning two values from a method). Tuples are a central part of functional languages like F#, and C# picked them up along the way.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
5

very useful for returning two values from a function

Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
4

Personally, I find Tuples to be an iterative part of development when you're in an investigative cycle, or just "playing". Because a Tuple is generic, I tend to think of it when working with generic parameters - especially when wanting to develop a generic piece of code, and I'm starting at the code end, instead of asking myself "how would I like this call to look?".

Quite often I realise that the collection that the Tuple forms become part of a list, and staring at List> doesn't really express the intention of the list, or how it works. I often "live" with it, but find myself wanting to manipulate the list, and change a value - at which point, I don't necessarily want to create a new Tuple for that, thus I need to create my own class or struct to hold it, so I can add manipulation code.

Of course, there's always extension methods - but quite often you don't want to extend that extra code to generic implementations.

There have been times I'm wanted to express data as a Tuple, and not had Tuples available. (VS2008) in which case I've just created my own Tuple class - and I don't make it thread safe (immutable).

So I guess I'm of the opinion that Tuples are lazy programming at the expense of losing a type name that describes it's purpose. The other expense is that you have to declare the signature of the Tuple whereever it's used as a parameter. After a number of methods that begin to look bloated, you may feel as I do, that it is worth making a class, as it cleans up the method signatures.

I tend to start by having the class as a public member of the class you're already working in. But the moment it extends beyond simply a collection of values, it get's it's own file, and I move it out of the containing class.

So in retrospect, I believe I use Tuples when I don't want to go off and write a class, and just want to think about what I've writing right now. Which means the signature of the Tuple may change quite a lot in the text half an hour whilst I figure out what data I am going to need for this method, and how it's returning what ever values it will return.

If I get a chance to refactor code, then often I'll question a Tuple's place in it.

3

Old question since 2010, and now in 2017 Dotnet changes and become more smart.

C# 7 introduces language support for tuples, which enables semantic names for the fields of a tuple using new, more efficient tuple types.

In vs 2017 and .Net 4.7 (or installing nuget package System.ValueTuple), you can create/use a tuple in a very efficient and simple way:

     var person = (Id:"123", Name:"john"); //create tuble with two items
     Console.WriteLine($"{person.Id} name:{person.Name}") //access its fields

Returning more than one value from a method:

    public (double sum, double average) ComputeSumAndAverage(List<double> list)
    {
       var sum= list.Sum();
        var average = sum/list.Count;
        return (sum, average);
    }

    How to use:

        var list=new List<double>{1,2,3};
        var result = ComputeSumAndAverage(list);
        Console.WriteLine($"Sum={result.sum} Average={result.average}");    

For more details read: https://learn.microsoft.com/en-us/dotnet/csharp/tuples

M.Hassan
  • 10,282
  • 5
  • 65
  • 84
1

A Tuple is often used to return multiple values from functions when you don’t want to create a specific type. If you're familiar with Python, Python has had this for a long time.

Randy Minder
  • 47,200
  • 49
  • 204
  • 358
1

A common use might be to avoid creating classes/structs that only contains 2 fields, instead you create a Tuple (or a KeyValuePair for now). Usefull as a return value, avoid passing N out params...

user347594
  • 1,256
  • 7
  • 11
1

Returning more than one value from a function. getCoordinates() isn't very useful if it just returns x or y or z, but making a full class and object to hold three ints also seems pretty heavyweight.

Dean J
  • 39,360
  • 16
  • 67
  • 93
0

I stumbled upon this performance benchmark between Tuples and Key-Value pairs and probably you will find it interesting. In summary it says that Tuple has advantage because it is a class, therefore it is stored in the heap and not in the stack and when passed around as argument its pointer is the only thing that is going. But KeyValuePair is a structs so it is faster to allocate but it is slower when used.

http://www.dotnetperls.com/tuple-keyvaluepair

WhatsUp
  • 73
  • 1
  • 7
Ognyan Dimitrov
  • 6,026
  • 1
  • 48
  • 70
0

Its really helpful while returning values from functions. We can have multiple values back and this is quite a saver in some scenarios.

Aishvarya Jaiswal
  • 1,793
  • 6
  • 34
  • 72
0

I find the KeyValuePair refreshing in C# to iterate over the key value pairs in a Dictionary.

Jubal
  • 8,357
  • 5
  • 29
  • 30
  • `KeyValuePair` can be viewed as special-purpose workaround. In Python, iterating over a `dict` just returns (key, value) tuples. – dan04 Jun 22 '10 at 01:56
  • Yes, like python. :-) I wasn't aware that KeyValuePair in c# wasn't a tuple? – Jubal Jun 22 '10 at 02:04