[Note: As Jon mentions in the comments, this is not a C# 4 feature but a .NET Framework 4 feature. I "loosely" ( and incorrectly ) labeled this as a C# 4 feature just because I am using C# below.]
A new Tuple type has been added to C# 4, which allows you to group different types into a single type. A Tuple is nothing new, just new to the C# language. In F#, for example, you can create a Tuple as simply as:
let data = (“John Doe”, 42)
which would create a tuple with a string as the first element and and integer as the second element.
printf “%A” data // Output: (“John Doe”,42)
Notice how elegant it is to create a Tuple in F#. Unfortunately things are not as elegant in C# 4.
To create a Tuple in C# 4 you can either create it using the new keyword as:
var data = new Tuple<string,int>(“John Doe”, 42);
or you can use one of the static Create Methods on Tuple itself like:
var data = Tuple.Create<string,int>(“John Doe”, 42);
Thankfully we have type inference so you can simplify it as such:
var data = Tuple.Create(“John Doe”, 42);
Note that I am intentionally showing a Tuple made up of two disparate types, but C# 4 has built-in support for several Create overloads to handle up to 8 parameters:
var data = Tuple.Create<T1,…,T8>(T1 Item1, … , T8 Item8);
If you want to access a particular item in the Tuple, you can access it via an ItemN property, where N is the number of the element in the Tuple. For example, to access the elements in the Tuple above one can use:
var item1 = data.Item1; // “John Doe” var item2 = data.Item2; // 42
Of course, you can go ahead an create lists of tuples and access them via LINQ to Objects:
var data = new List<Tuple<string,int>>();
data.Add(Tuple.Create("John Doe", 42));
data.Add(Tuple.Create("Jane Doe", 22));
var item = (from t in data
where t.Item2 == 42
select t).SingleOrDefault();
Console.WriteLine("Item1: {0}, Item2: {1}", item.Item1, item.Item2);
Console.ReadLine();
A Tuple is often used to return multiple values from functions when you don’t want to create a specific type. Although not a perfect analogy, this is somewhat similar to how one uses Anonymous Types, except that Anonymous Types cannot go outside a method boundary like a Tuple.
Hope this helps.

I hate to sound like a broken record, but similar to Zip, Tuple is something Pyrhon has had for ages.
I love that C# is becoming a hybrid language by supporting traditionally dynamic language features. On the other hand, I sometimes cannot help myself from thinking "Why not just use a dynamic language instead?"
Posted by: Edward J. Stembler | 01/01/2010 at 10:17 AM
this is great. thanks for sharing this post. the one problem i had with anonymous types is that they couldn't cross method boundaries, but it looks like tuples will solve this problem.
Posted by: Johnnyo | 01/01/2010 at 12:17 PM
Quick bit of pedantry: unless I've missed something (in which case I *really* want to know about it ASAP!) this isn't a feature of C# 4 at all - it's a feature of the .NET 4.0 framework library. The C# *language* doesn't know anything about tuples, does it?
I only ask because the language *could* have known about them - it could have done interesting things with methods returning tuples, for instance, as other languages do.
Posted by: Jon Skeet | 01/01/2010 at 01:27 PM
You're correct, Jon. It is a feature of the .NET Framework 4.
I just loosely labeled it as more of a C# 4 feature because I was using C# in the examples.
Thanks for pointing that out.
Posted by: David Hayden | 01/01/2010 at 01:59 PM
@David: Phew - I thought I might have an extra section to add into my 2nd edition :)
@Edward: What do Zip and Tuple have to do with dynamic languages? What's "dynamic" about the Zip operator? C# 4 and .NET 4.0 certainly *do* have dynamic features (via the DLR) but tuples and the zip operator are pretty statically typed as far as I can see... in particular, neither require you to lose any static type information.
If you like statically typed languages but you happen to want a tuple or a zip operator, why on earth would you change to a dynamic language just to get them?
Posted by: Jon Skeet | 01/01/2010 at 02:20 PM
I was about to dismiss the entire Tuple feature in favor of Anonymous Types until I read the very last sentence. What allows Tuple to get past the method return boundary, but not Anon. Types?
Thanks.
Posted by: Murrayondotnet | 01/01/2010 at 02:52 PM
@Murrayondotnet - simply that there is no way of expressing the return type for an anon-type, except for cheating with "object" (and either using "dynamic", reflection, or cast-by-example to get the values back out). Tuples are a well-defined set of types, so can be declared as a return type.
Posted by: Marc Gravell | 01/01/2010 at 03:18 PM
I really hope this does become a feature of C# 4. I won't want to write "Tuple.Create" any more than I want to write "Enumerable.Select".
Maybe C# still has a lesson or two to learn from Python.
Posted by: Richard Poole | 01/01/2010 at 03:18 PM
We have modified Mono's C# compiler to support Tuples natively so that you get Perl-like syntax on assignment and we are extending it to support tuple creation like the sample for F#.
Patch and samples here:
http://tirania.org/blog/archive/2009/Dec-23.html
Posted by: Miguel de Icaza | 01/01/2010 at 04:23 PM
a couple of questions:
When you have a Tuple longer than 8 items, can you just add another Tuple, i.e. can you have Tuples of Tuples?
An advantage of the use of anonymous types is that you can name the properties, i.e. var blah = new { Name = string.Empty };. is there anyway to name the types of a Tuple differently from .Item1 .. .Item8?
Posted by: Paul_spencer | 01/05/2010 at 11:32 AM
Paul,
You have to use nested tuples when you have 8 or more items. The Tuple.Rest Property allows you to access those eight through nth items in the nested tuples.
You can read more here:
http://www.davidhayden.me/2010/01/tuplerest-property-and-nested-tuples.html
As far as I know there is no way to rename the Item1, Item2, etc. properties on a Tuple to make them more meaningful.
Posted by: David Hayden | 01/05/2010 at 03:16 PM