Will a future version of .NET support tuples in C#?

33,354

Solution 1

I've just read this article from the MSDN Magazine: Building Tuple

Here are excerpts:

The upcoming 4.0 release of Microsoft .NET Framework introduces a new type called System.Tuple. System.Tuple is a fixed-size collection of heterogeneously typed data.    

 

Like an array, a tuple has a fixed size that can't be changed once it has been created. Unlike an array, each element in a tuple may be a different type, and a tuple is able to guarantee strong typing for each element.

 

There is already one example of a tuple floating around the Microsoft .NET Framework, in the System.Collections.Generic namespace: KeyValuePair. While KeyValuePair can be thought of as the same as Tuple, since they are both types that hold two things, KeyValuePair feels different from Tuple because it evokes a relationship between the two values it stores (and with good reason, as it supports the Dictionary class).

Furthermore, tuples can be arbitrarily sized, whereas KeyValuePair holds only two things: a key and a value.


While some languages like F# have special syntax for tuples, you can use the new common tuple type from any language. Revisiting the first example, we can see that while useful, tuples can be overly verbose in languages without syntax for a tuple:

class Program {
    static void Main(string[] args) {
        Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
        PrintStringAndInt(t.Item1, t.Item2);
    }
    static void PrintStringAndInt(string s, int i) {
        Console.WriteLine("{0} {1}", s, i);
    }
}

Using the var keyword from C# 3.0, we can remove the type signature on the tuple variable, which allows for somewhat more readable code.

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

We've also added some factory methods to a static Tuple class which makes it easier to build tuples in a language that supports type inference, like C#.

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

Solution 2

#region tuples

    public class Tuple<T>
    {
        public Tuple(T first)
        {
            First = first;
        }

        public T First { get; set; }
    }

    public class Tuple<T, T2> : Tuple<T>
    {
        public Tuple(T first, T2 second)
            : base(first)
        {
            Second = second;
        }

        public T2 Second { get; set; }
    }

    public class Tuple<T, T2, T3> : Tuple<T, T2>
    {
        public Tuple(T first, T2 second, T3 third)
            : base(first, second)
        {
            Third = third;
        }

        public T3 Third { get; set; }
    }

    public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3>
    {
        public Tuple(T first, T2 second, T3 third, T4 fourth)
            : base(first, second, third)
        {
            Fourth = fourth;
        }

        public T4 Fourth { get; set; }
    }

    #endregion

And to make declarations prettier:

public static class Tuple
{
    //Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2")
    public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2)
    {
        return new Tuple<T1, T2>(t1, t2);
    }
    //etc...
}

Solution 3

There is a proper (not quick) C# Tuple implementation in Lokad Shared Libraries (Open-source, of course) that includes following required features:

  • 2-5 immutable tuple implementations
  • Proper DebuggerDisplayAttribute
  • Proper hashing and equality checks
  • Helpers for generating tuples from the provided parameters (generics are inferred by compiler) and extensions for collection-based operations.
  • production-tested.

Solution 4

Implementing Tuple classes or reusing F# classes within C# is only half the story - these give you the ability to create tuples with relative ease, but not really the syntactic sugar which makes them so nice to use in languages like F#.

For example in F# you can use pattern matching to extract both parts of a tuple within a let statment, eg

let (a, b) = someTupleFunc

Unfortunately to do the same using the F# classes from C# would be much less elegant:

Tuple<int,int> x = someTupleFunc();
int a = x.get_Item1();
int b = x.get_Item2();

Tuples represent a powerful method for returning multiple values from a function call without the need to litter your code with throwaway classes, or resorting to ugly ref or out parameters. However, in my opinion, without some syntactic sugar to make their creation and access more elegant, they are of limited use.

Solution 5

In my opinion, the anonymous types feature is not a tuple, but a very similar construct. The output of some LINQ Queries are collections of anonymous types, which behave like tuples.

Here is a statement, which creates a typed tuple :-) on the fly:

var p1 = new {a = "A", b = 3};

see: http://www.developer.com/net/csharp/article.php/3589916

Share:
33,354
Graviton
Author by

Graviton

A software developer.

Updated on September 24, 2020

Comments

  • Graviton
    Graviton over 3 years

    .Net 3.5 doesn't support tuples. Too bad, But not sure whether the future version of .net will support tuples or not?

  • Sebastiaan
    Sebastiaan over 15 years
    While the question is on MS providing it in .NET 4, this is a good way to manage it for now. +1
  • Marc Gravell
    Marc Gravell over 15 years
    "C# has been drifting more dynamic" - no, it has been drifting more implicit/inferred; it is still a fully static language. However, better dynamic support (for consuming DLR classes) is a very likely future language enhancement.
  • Meydjer Luzzoli
    Meydjer Luzzoli over 15 years
    How do you explain the presence of tuples in F#, or Haskell, or any of the other strongly and statically typed languages that have full support for them then...?
  • Meydjer Luzzoli
    Meydjer Luzzoli over 15 years
    One of the benefits is for things like TryParse, where you can write 'valid value = double.TryParse("1.02")' and have multiple return values assigned without any clumsy out parameters. But in general I agree that purely positional data structures aren't a great thing to pass around.
  • Sebastiaan
    Sebastiaan over 15 years
    How about anonymous types, then?
  • Chris Ballard
    Chris Ballard over 15 years
    That allows you to replace Tuple<int,int> with var, but you still end up with three lines of code rather than one
  • Adam Lassek
    Adam Lassek over 15 years
    Perhaps this is something we will see in C# 4.0. Syntactic sugar such as int a, b = someTupleFunc(); should be perfectly doable at a compiler level.
  • Joel Mueller
    Joel Mueller over 15 years
    This inheritance approach is fine if you don't need to compare two Tuples for equality. I wanted to implement IEquatable<Tuple<T1, T2>> and so forth in my implementation, so I couldn't use inheritance, because I didn't want a Tuple<T1,T2> to be equal to a Tuple<T1,T2,T3,T4>.
  • Daniel O
    Daniel O about 15 years
    Just like if statements are just gotos with a block of statements. Tuples are nice if you have you are used to them and classes seem unneccessary and unwieldy in specific cases...
  • RossFabricant
    RossFabricant about 15 years
    @Joel, You can have Equals check the dynamic type of both arguments.
  • Andriy Drozdyuk
    Andriy Drozdyuk about 15 years
    How would you use it in code? t = new Tuple(1, 2); t.First and t.Second?
  • tina Miller
    tina Miller almost 15 years
    See also another answer to similar question: stackoverflow.com/questions/955982/…
  • tina Miller
    tina Miller almost 15 years
    @drozzy, no, you would have to do t = new Tuple<int, int>(1, 2);
  • tina Miller
    tina Miller almost 15 years
    @dimarzionist, sorry for editing your post, I tried a comment but it was unreadable, feel free to delete or modify.
  • Walt W
    Walt W over 13 years
    Agreed - multiple return values is the best use case for tuples, and other than that there is very little purpose for tuples in code. That should be a convention rather than a restriction though where tuples are allowed. What I think would have been neater is if .NET languages provided a way to "disect" return objects into multiple values rather than introducing the tuple data type. Something like { j = ErrorCode, h = ResultObj } = SomeFunction() (where j and h are locals) would have been much more helpful than tuples.
  • Callum Rogers
    Callum Rogers about 11 years
    I see you use inheritance - do you really want to be able to pass a Tuple<T1,T2,T3> as a Tuple<T1,T2>? The answer is likely no.
  • nawfal
    nawfal almost 10 years
    But that is not all. If it is based on inheritance, I suppose you could write Tuple<Int32, String> t1 = new Tuple<Int32, String, Boolean>(10, "a", true); etc. I'm not sure if there is any scenario this is desired.
  • tm1
    tm1 over 6 years
    This works out of the box as of .NET 4.7, since older versions of .NET don't contain the needed ValueTuple structures. However, you can provide these, for example by means of a NuGet package like ValueTupleBridge.
  • Admin
    Admin about 6 years
    MS now has an official nuget package for the required tuple class(es)
  • AustinWBryan
    AustinWBryan about 6 years
    Unless you need to return 5 items from a function, that is. And sure, you could make you're own generic class, but the syntax in C# 7 is so much cleaner and simpler.