New Tuple features and deconstruction with Tuples in C# 7

Tuples have been available in C# for some time now. C# 7 comes with a handful of new things for tuples though.

Let’s see an example for using tuples in the old way. The following function returns a Tuple with two integers: the first is the total days of a duration and the second is the total hours of a duration. Not the most useful function that the world has ever seen, but it’s good for demo purposes:

private Tuple<int, int> AnalyseDatesOld(DateTime first, DateTime second)
{
	TimeSpan timespan = (second - first).Duration();
	return new Tuple<int, int>(Convert.ToInt32(timespan.TotalDays), Convert.ToInt32(timespan.TotalHours));
}

…and then we can call this function and retrieve the individual parts of the tuple as Item1 and Item2:

public void OldWay()
{
	var t = AnalyseDatesOld(DateTime.UtcNow, DateTime.UtcNow.AddDays(10));
	Console.WriteLine(t.Item1);
	Console.WriteLine(t.Item2);
}

The code works fine, but it’s not easy to know what Item1 and Item2 refer to.

Before we continue, just as a short aside, we can also build tuples with the static Create function:

return Tuple.Create(Convert.ToInt32(timespan.TotalDays), Convert.ToInt32(timespan.TotalHours));

One addition to tuples is that we can give names to the various items in them. Here’s an updated version of the above function:

private (int TotalDays, int TotalHours) AnalyseDatesNew(DateTime first, DateTime second)
{
	TimeSpan timespan = (second - first).Duration();
	return (Convert.ToInt32(timespan.TotalDays), Convert.ToInt32(timespan.TotalHours));
}

Note how we sort of have multiple return types in the signature with two integers within parentheses and both integers have names: TotalDays and TotalHours. Also, the return value will be built in a similar fashion, i.e. two elements within parens, delimited by a comma. Therefore we don’t use the tuple creation techniques we presented above. The reason for that is that the return type of this new function is not exactly Tuple, but it’s rather System.ValueTuple. Also note, that System.ValueTuple is NOT available by default in .NET 4.6.2. If your project is set up with that version of .NET then the compiler will complain about funny syntax with the parens. There are two ways out of this situation:

  • Upgrade the target framework of the project (assembly) to at least 4.7 in the project properties window
  • Install the System.ValueTuple NuGet package if your target framework must not exceed 4.6.2

Here’s how we can call the ValueTuple function and access its properties:

var t = AnalyseDatesNew(DateTime.UtcNow, DateTime.UtcNow.AddDays(10));
Console.WriteLine(t.TotalDays);
Console.WriteLine(t.TotalHours);

We can also override the names of the returned variables:

(int days, int hours) t2 = AnalyseDatesNew(DateTime.UtcNow, DateTime.UtcNow.AddDays(10));
Console.WriteLine(t2.days);
Console.WriteLine(t2.hours);

This technique is called deconstruction, when we dissect the elements of an object and assign them to various variables.

We can even forget the variable assignment and still use deconstruction:

(int d, int h) = AnalyseDatesNew(DateTime.UtcNow, DateTime.UtcNow.AddDays(10));
Console.WriteLine(d);
Console.WriteLine(h);

So the elements returned by AnalyseDatesNew are directly assigned to the variables “d” and “h” without any other variable assignment in between.

The above is equivalent to the following syntax:

int d2, h2;
(d2, h2) = AnalyseDatesNew(DateTime.UtcNow, DateTime.UtcNow.AddDays(10));

We can also declare the deconstructed variables with “var” and the compiler will figure out their exact types:

var (dateDays, dateHours) = AnalyseDatesNew(DateTime.UtcNow, DateTime.UtcNow.AddDays(10));
Console.WriteLine(dateDays);
Console.WriteLine(dateHours);

Other bits and pieces with Tuples

We can create ad-hoc objects with inline tuples, i.e. where we declare the property names and values within parens:

var dog = (Name: "Doge", Colour: "Black", Age: 5);
Console.WriteLine($"Name: {dog.Name}, Colour: {dog.Colour}, Age: {dog.Age}");

Tuple property names can be inherited by other tuples like in the following example:

var myCat = (Name: "Missy", Colour: "White", Age: 4);
var myOtherCat = (myCat.Name, Colour: "Black", myCat.Age);

Note how “myOtherCat” has no property name declaration for the name and age fields. We can still refer to them by Name and Age since those names have been transferred from “myCat”:

Console.WriteLine(myOtherCat.Name);
Console.WriteLine(myOtherCat.Colour);
Console.WriteLine(myOtherCat.Age);

A similar feature can be observed in the following case, although it’s not perfect:

string[] colours = new[] { "Black", "White", "Blue", "Red" };
var colourTuples = colours.Select(c => (c.ToUpper(), c.ToLower(), c.Length));
foreach (var item in colourTuples)
{
	Console.WriteLine(item.Item1);
        Console.WriteLine(item.Item2);
	Console.WriteLine(item.Length);
}

So we return a tuple with 3 elements: the capitalised colours, the lowercase colours and their lengths and then we print these properties. Note, how the Length property has been transferred to the colourTuples list of tuples. The ToUpper and ToLower function names are, however, missing and we need to refer to them with Item1 and Item2. So this name transfer feature currently only works with property names, not functions.

View all various C# language feature related posts here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT BEST PRACTICES WITH MICROSOFT STACK & ANGULAR

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: