The world of .NET and Web Programming

C# 4.0/BCL 4 Series: System.Tuple

I mentioned, in my last post, that I was using  C# 4.0 In A Nutshell to better my C# 3 and to come up to speed with C# 4/BCL 4. Another cool thing in Framework 4.0 is the generic set of classes for holding a set of differently typed objects called tuples. Like the Func<> and Action<> delegates, tuples also take up to 8 parameters:

public class Tuple<T1>

up to:

public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>

While C# and VB.NET do not have the concept as part of the core language, many functional languages have tuples as common features. Also many teams have built their own. The BCL 4 System.Tuple is the one definition to rule all others and there is one interoperable type.

Above, each of the tuples has read-only properties called Item1, Item2 and so on (one for each type parameter). You can instantiate a tuple either via it's constructor:

var t = new Tuple<int, string> (123, "Hello");

or via the static helper method Tuple.Create:

Tuple<int, string> t = Tuple.Create(123, "Hello");

which can be made:

var t = Tuple.Create(123, "Hello");

You can then access the properties as (Note: each is statically typed):

Console.WriteLine(t.Item1 * 2);                     // 246

Console.WriteLine(t.Item2.ToUpper());         // HELLO

You may ask what Tuples are good for? They are really convenient in returning more than one value from a method or creating collections of value pairs. You could use object arrays but then you lose static type safety, incur the cost of boxing/unboxing for value types, and require clumsy casts that cannot be validated by the compiler.

Now to return to the subject of the last post, comparisons. Tuples are classes so they are reference types. This means, comparing two distinct instances with the equality operator returns false. Unlike arrays however, the Equals method is overridden to compare each individual element instead:

var t1 = Tuple.Create(123, "Hello");

var t2 = Tuple.Create(123, "Hello");

Console.WriteLine(t1 == t2);                        // False

Console.WriteLine(t1.Equals (t2));               // True

Last time, I talked about the StructuralComparison type. Well, tuples implement IStructuralEquatable, so you can pass in a custom equality comparer.

If you want to learn a lot more about System.Tuple, you can look at the excellent MSDN article: "CLR Inside Out: Building Tuple" http://msdn.microsoft.com/en-us/magazine/dd942829.aspx

 

» Similar Posts

  1. C# 4.0/BCL 4 Series:Dynamic Primitive Type Part 2
  2. C# 4.0/BCL 4 Series: StructuralComparisons Type
  3. C# 4.0/BCL 4 Series:Dynamic Primitive Type Part 1

» Trackbacks & Pingbacks

  1. Pingback from Twitter Trackbacks for Framework 4.0: System.Tuple : Sam Gentile's Blog (if (DeveloperTask == Communication && OS == Windows) [samgentile.com] on Topsy.com

  2. Pingback from Friday Links #100 | Blue Onion Software *

  3. Might as well make this a series. I mentioned in the first post , &quot;I have been spending quite a bit of time re-focusing and reviewing C# (and some BCL) fundamentals, with an eye to what's different in C# 4.0/BCL 4.0. The reason for this, is though

    C# 4.0/BCL 4: What's New Series — May 10, 2010 2:06 AM
  4. I mentioned, in my last post, that I was using C# 4.0 In A Nutshell to better my C# 3 and to come up to speed with C# 4/BCL 4. Another cool thing in Framework 4.0 is the generic set of classes for holding a set of differently typed objects called tuples

Trackback link for this post:
http://samgentile.com/Web/trackback.ashx?id=1902

» Comments

  1. Steve Johnson avatar

    Sam, IMHO I think we should be VERY judicious with our use of Tuple and the var keyword. In fact, I don't think we have any business using Tuple in C# code except where required for language interop. It's really not so much trouble to define an explicit type where a Tuple could be used. As for var, I think the only place that has legit use as with LINQ. This is just my opinion, but the recent perversion of the C# language makes me throw up in my mouth a little bit. Is it really too much trouble to type:

    int i = 123;

    ...or...

    string s = "the string";

    etc...?

    The only use for these two "features" appears, to me, to be to facilitate programmer laziness and sloppiness. No offense to you or the language is intended. It's just food for thought.

    Steve Johnson — May 4, 2010 4:35 PM
  2. samgentile avatar

    I do agree to be very judicious in use of var. I think it should be used only when using anonymous types or it will make the code cleaner to read. I don't think the C# designers designed it for programmer lazziness and sloppiness. There are places where the type is unknown like anonymous types. I don't see the wrong or judicious use remark as it applies to tuples though. What's the issue? Thanks for your comments.

    samgentile — May 4, 2010 5:26 PM
  3. Steve Johnson avatar

    My problem is that they're not explicit, and they're just not necessary for everyday C# coding tasks. Writing code that addresses Item1, Item2, ItemN... greatly reduces readability and maintainability, IMO. A compromise I could live with is an anonymous type with explicit member names. At least then the code would be readable. There's clearly a time and a place for System.Tuple, but I don't think we should use them merely for coding convenience. CLR 4 and FCL 4 ROCK, but C# 4 seems to be reaching for features. The language was complete a few years ago, IMO.

    Steve Johnson — May 4, 2010 11:04 PM
  4. Steve Johnson avatar

    Actually, I shouldn't be criticizing C# 4, because these aren't C# 4 features, so I take that back. It's just the proliferation of these coding practices of late that bother me.

    Steve Johnson — May 4, 2010 11:08 PM
  5. samgentile avatar

    I have to agree that the language was done a couple of years ago. C# 3 in .NET 3.5 yea, C# 4 with Dynamic types, etc - bleh

    samgentile — May 5, 2010 6:25 PM
  6. Darren Neimke avatar

    >> Is it really too much trouble to type:

    >> int i = 123;

    or,

    Dictionary<DateTime, FarmAnimal> p = new Dictionary<DateTime, FarmAnimal>() ;

    Yes, it is :-)

    Darren Neimke — May 10, 2010 4:48 AM
  7. Matt Warren avatar

    @Steve I have an un-official coding rule of not using "var" for value types or strings, because there's just too many problems, it's not obvious what the follow does unless you reall know the number specifiers

    var num = 5.6m

    var num = 5.6f;

    But for the example from @Darren, it's obvious what the following does:

    var p = new Dictionary<DateTime, FarmAnimal>() ;

    Matt Warren — May 11, 2010 9:15 AM
  8. Andre avatar

    @Steve Johnson

    var isn't there to facilitate programmer sloppiness and laziness. The point of these new features is to let the compiler deal with types. I bet you don't miss the days of prefixing variables based it's type. I get sick to my stomach every time I read C++ documentation and see something like "lpwstrName". A lot of these features are spilling over from functional programming (where the compiler deals with typing) to help tackle multi/many core programming, so except more in future.

    Andre — May 23, 2010 10:54 AM
  9. George avatar

    @Steve Johnson, et al.

    I am all for cutting down on the housekeeping. I am tired of nursing the compiler. You might call it laziness, but the less houekeeping I need to do the more intentional stuff I am free to write.

    The language is far from done. There are probably many more changes that could make coding more readily expressive of the domain rather than merely the implementation.

    George — September 18, 2010 7:48 PM

» Leave a Comment