ReSharper’s Extract Method refactoring with better C# 6 and C# 7 support

If you are using the latest ReSharper 2017.3 EAP build, you may have noticed a few changes in the Extract Method refactoring, which now comes with better support for C# 6 and C# 7. Support for local functions has been added, there’s now an option to return value tuple instead of out parameters, and Extract Method now works in expression-bodied members. Let’s see!

Extract to local function

Starting with C# 7.0 we can make use of local functions – private methods that are nested in another member and that can only be called from their containing member. ReSharper 2017.3’s Extract Method refactoring (Ctrl+R, M) now supports extracting a bit of code into a full method, or into a local function:
Extract code into local function - Refactoring with ReSharper

When extracting code into a local function, we can specify its scope. We can place it at the beginning (or the end) of the containing member, or just before/after its usage.
Local function scope

If required closures aren’t available at the selected location, they will be converted to parameters. For example, take the following piece of code:

If we extract the Console.WriteLine(message); statement into a local function, ReSharper will generate different code depending on the location we place that function. If we place the generated function at the start of Method(), the message closure is not yet available and our local function will require a parameter:
Local function generated with parameter if closure unavailable

If we place the local function further down in our containing method, the message closure is available and can be accessed by our local function:
Local function uses closure

Note that it’s always possible to use parameters instead of closures, by explicitly checking them in the refactoring UI.

Smart extraction of local functions in conflicting code

Local functions are often located at the beginning/end of their containing method (examples in Microsoft’s C# programming guide). This makes it often impossible to extract methods easily, as it would require selecting multiple lines of code at various locations in our code.

ReSharper 2017.3 helps by extracting both the selected line(s) of code as well as the local function that is required by it:
ReSharper Extract Method refactoring includes local functions

Similarly if it would not be possible to keep the local function in its containing member, ReSharper will extract it into a regular method:
ReSharper converts local function to regular method if required by calling code

Return value tuple instead of out parameter

When using C# 7.0 in our code base, the Extract Method refactoring now add a option to return value tuples instead of working with out parameters. When extracting a method (or local function), we can now choose whether we want to return a single value and assign one or more out parameters, or return multiple values using a C# 7.0 tuple:
Multiple return values using value tuples in ReSharper's Extract Method

Other C# 6.0 and C# 7.0 improvements

ReSharper 2017.3’s Extract Method refactoring now better handles C# 6.0 and C# 7.0 code features:

  • Extract Method is now available from expression-bodied members.
  • Conflict resolution for nameof() usages.
  • Better usage of C# 7.0 syntax when rewriting code during method extraction.
  • Generation of out var at the call site, as well as removing readonly from properties if needed.

Depending on the options we select in the Extract Method refactoring UI, ReSharper will use the preferred C# 6.0 or C# 7.0 syntax:
Extract Method respects C# 7.0 syntax options

Download ReSharper 2017.3 EAP now and give it a try! We’d love to hear your feedback.

This entry was posted in How-To's and tagged , , , , , , . Bookmark the permalink.

3 Responses to ReSharper’s Extract Method refactoring with better C# 6 and C# 7 support

  1. Steve says:

    What date will be released?

  2. oli says:

    thank you jetbrains!

Leave a Reply

Your email address will not be published. Required fields are marked *