Let’s talk about one of the cool new features of C# 7.0 - deconstruction. Quite often you might need to return more than one value from a method, which can be accomplished in several ways:
refarguments (usually considered a code smell)
- create a more meaningful class/struct that represents the result of calling the method (a preferable option, especially as the number of returned values grows)
System.Tuple(some kind of a middleground)
They all work, but in fact only a special return type feels like a good solution, since both
out arguments and explicitly used tuples look just like a boilerplate code and don’t contribute to readable code.
Update 2017-04-09: As pointed out by Julien Couvreur in the comments, I made some incorrect conclusions about how compiler actually deconstructs ValueTuples. I assumed that this is done using the extensions methods in the System.ValueTuple NuGet package, while they are clearly declared on the older
System.Tuple type and are NOT being used for the deconstruction. In fact, C# compiler has built-in knowledge for ValueTuple type, so no extensions needed. More detailed explanation is available in this document in Roslyn repository on Github.
Before C# 7.0
As an example, I’ll use a very simple
GetPositiveNumber method, which generates a random integer in the [-3, 3] interval and returns both the number and a boolean flag, specifying whether the nuber was actually positive. In previous versions of C#, if we followed the common
Try... method pattern, it could look like this (imagine all of the following code to be inside a class):
Rewritten with tuples, it would look not too different (but at least without
Not too bad. It already shows the intent of the code much better: clearly, the method returns two things packed into a container type. But when we try to write the code that calls this method, it begins to look ugly:
Item2 properties don’t really mean anything to the reader, they describe neither purpose, nor type. And this is exactly the problem that was solved with
ValueTuple and deconstruction in C# 7.0.
What really felt wrong in the previous version of our code is that we could not give the tuple properties meaningful names and also we needed to first assign the tuple itself to a variable and only after that we could access the values. If you think about it, this is redundant: we are not interested in the tuple itself, we just want our values! So, C# 7.0 allows us to write the same functionality in a much shorter way:
(IMPORTANT: for this to work, you need to manually install a System.ValueTuple NuGet package to your project, since the compiler will use types from it.)
This way both values we are actually interested in are immediately assigned to the corresponding variables - all in one line! Also, the method signature now reads much better, since it is quite obvious that there are two return values.
After 12 years of .NET development, this looks like magic. And I don’t like magic. So, if you are like me, the next thing you do is open your favourite IL disassembler (mine is ILSpy) and see what actually happens behind the scenes.
So, essentially everything we wrote was just syntactic sugar, which then was turned into using a concrete
System.ValueTuple struct. We can also see that the method is now marked with a
TupleElementNames attribute, which kept the names of the values returned by the original method. Obviously, we can deconstruct to local variables with any names, so this information is only preserved for displaying an Intellisense hint, when you hover over the method:
If we look at
ValueTuple<T1,T2> itself, there is nothing really interesting, just a struct with (again!)
So, how does this struct get assigned to two variables at once? Turns out, the compiler will use duck-typing and check if there is
Deconstruct method available on the type we are, well, deconstructing. Actually, the method doesn’t have to be defined in the type itself, it can be declared as an extension method - which is exactly the case for
Finally, the magic is revealed! The C# compiler will convert our nice and readable code into a bit more boring code using
ValueTuple, and if there is a deconstruction statement used in the calling code, it will be rewritten with the
Deconstruct method, if such exists.
Edit 2017-04-09: Turns out I was wrong here (thanks to Julien Couvreur for correcting me): C# compiler has built-in knowledge of
System.ValueTuple type, and moreover, the extensions methods above are clearly defined on a completely different type and have nothing to do with C# deconstruction syntax.
This bring us to another interesting question: can we only use deconstruction with these value tuples or with custom types as well?
Deconstructing custom types
Since we already saw that deconstruction works by using duck-typing, you can guess that the same trick works with our custom return types too. When might this be useful? Imagine you already have some method that returns a class, not a tuple, and you still want to leverage the deconstruction pattern when calling this existing method. Most likely you wouldn’t want to rewrite the method to use tuples (too much work probably) - and luckily you don’t have to! Just defining an extension method
Deconstruct on the return type is enough to make compiler happy:
This is, in my opinion, the best way to write this kind of code, since we managed to combine the best of both worlds: the method now returns a type with a meaningful name (and can easily be extended with more properties, if necessary), while, with the help of an extension method, we could deconstruct the result into two local variables - still in one line.
One shouldn’t underestimate such language improvements: even though there is, strictly speaking, no new functionality here, it greatly reduces the amount of boilerplate code and improves redability by making the intent of a method much clearer. After all, human time is the most expensive resource in software development, so having less lines of code to read (without sacrificing readability) is a big win.