.NET Tools
Essential productivity kit for .NET and game developers
C# 7.0 and 7.1 support in ReSharper – Tuples
ReSharper 2017.1 and 2017.2 bring better support for C# 7.0 and C# 7.1, with a number of new inspections, quick-fixes and context actions. In this 6th part of our blog series, let’s cover how ReSharper (and Rider) work with tuples and how they help with inferring tuple names (spec) in our code. Tuples have been around for a while, and keep evolving in both C# as well as in ReSharper’s features that you know and love.
In this series:
Tuples
Before, if we had a situation where we needed to pass around a few values (e.g. as a function return value or in a LINQ expression), we’d have to resort to the System.Tuple<T1, T2, ...>
types. Tuples allow us to pass around values of any type using their properties Item1
, Item2
, …, without having to create a specialized object for those cases.
With C# 7.0 came language support for tuples and deconstruction. Instead of having to use these clunky objects (that are allocated on the managed heap and thus cause additional memory traffic), we can now use the ValueTuple
type (which is a struct) using plain C# code:
// Before: private Tuple<string, int> GetNameAndAge() { return new Tuple<string, int>("Maarten", 33); } private void Example() { var nameAndAge = GetNameAndAge(); var name = nameAndAge.Item1; var age = nameAndAge.Item2; // ... } // After: private (string, int) GetNameAndAge() { return ("Maarten", 33); } private void Example() { var (name, age) = GetNameAndAge(); // ... }
More concise, and better in terms of memory usage and allocations. Still, the properties of the tuple returned by GetNameAndAge()
are named Item1
and Item2
. We can do better, and use custom names by adding those in the GetNameAndAge()
return type:
C# 7.1 adds another language feature on top: tuple projection initializers. This allows us to use tuples in projections (e.g. in LINQ), and have the language infer the property names for us. So instead of explicitly having to name our tuple values, they are inferred from the source object (in this case Person
):
var person = list .Select(p => (p.Name, p.Age)) // instead of: .Select(p => (Name: p.Name, Age: p.Age)) .FirstOrDefault(tuple => tuple.Age > 21); Console.WriteLine(person.Name); Console.WriteLine(person.Age);
ReSharper comes with an inspection and corresponding quick-fix that reveals redundant tuple value names when they can be inferred from initializer:
ReSharper comes with a number of other inspections. For example, it detects unused code and will let us use a quick-fix to, instead of assigning a variable, insert a “discard” (in the form of a _
):
ReSharper can also detect typos in variable names when overriding a method or implementing an interface. A quick-fix can resolve the issue for us:
Note if you want to use this language feature, the ValueTuple
type is required. It’s built into .NET 4.7, .NET Core 2.0, Mono 5.0 and .NET Standard 2.0 – for other target frameworks make sure to install the System.ValueTuple package.
Download ReSharper Ultimate or check out Rider that takes advantage of ReSharper’s language support updates. We’d love to hear your thoughts.