While I had originally written about my lack of appreciation for Tuples in .Net 4, the new Tuple feature that has been introduced with C# 7 is really something else.
Having programmed in functional languages like F#, a good Tuple implementation is something I’ve come to appreciate.
Here are the reasons the new Tuple is better than the old one.
Field names
Tuple fields now have names which makes reasoning about the code a whole lot easier.
Compare this:
var oldTuple = Tuple.Create(1, "test", 1.0); var b = oldTuple.Item1 == 2 ? oldTuple.Item2.ToLower() : "";
With this:
(int rebate, string itemName, double price) newTuple = (1, "test", 1.0); var a = newTuple.rebate == 2 ? newTuple.itemName.ToLower() : "";
Gone are the Item1 and Item2 fields.
Better syntax support
As you can see in the previous example Tuples can be manipulated using the parentheses syntax. There is no need to use the Tuple type’s Create method.
Here’s an example of the new syntax being used to define a Tuple return type for a method.
public (string first, string second) ReturnTuple() { return ("an", "example"); }
Deconstruction support
Deconstruction is another feature that F# and some functional programmers (or Rust programmers for that matter) are probably familiar with and that you can now use with Tuples.
Here is an example:
public class FromHellsHeart { public bool GrapplingWithThee { get; set; } public bool StabingAtThee { get; set; } public bool SpitingAtThee { get; set; } public void Deconstruct(out bool grappling, out bool stabbing, out bool spitting) { grappling = GrapplingWithThee; stabbing = StabingAtThee; spitting = SpitingAtThee; } } [TestMethod] public void TupleTest() { var mobyDick = new FromHellsHeart { GrapplingWithThee = true, StabingAtThee = true, SpitingAtThee = true, }; (bool g, bool st, bool sp) = mobyDick; Assert.IsTrue(g && st && sp); }
By deconstructing the mobyDick Tuple we have essentially extracted it’s elements into three local variables.
Conclusion
All these new features bring Tuples in line with languages like F# which is a good thing.
Tuples are a great way to prevent having to write one off classes, to easily refactor methods that would need to pass around anonymous types or to replace the older less efficient Tuple.