Non-trailing named arguments in ReSharper 2018.1 EAP

Whenever we pass a value to a constructor or method, named arguments can help clarify to which parameter an argument is being bound. Being quite helpful most of the times, it had one downside by times: argument names had to be added for all following arguments as well, simply to make the compiler happy. This was fixed with non-trailing argument names in C# 7.2 and we added full support for this in ReSharper 2018.1 EAP. Let’s explore what named arguments can do for us!

Improve readability

Especially for literals like true, false, null, numbers and strings, it is often hard to tell what they do. Consider this snippet:

Looking at these invocations, it’s difficult to say what those literals actually mean. 1000 and two times true? What’s that for? We could use something like Go To Declaration (F12), ParameterInfo (Ctrl+Shift+Space) or even debugging to find out, but that’s not very convenient. Since C# 4 we can use named arguments, which is a zero-effort-solution for future readers of our code.

One major drawback since C# 4 was that whenever we wanted to add the argument name for a single argument, all following arguments had to have their name added as well. Writing cancellationToken: cancellationToken is not providing us with many benefits but language noise. With the release of C# 7.2 we can make use of non-trailing named arguments and add the name only at the positions we really want. However, they still must occur in their correct position, so that the compiler can figure out to which parameter it should be bound:

If you experience any syntax errors given the example above, you may need to adjust our language version.

Another good thing to know is that C# 7.2 also removes the limitation of using named arguments in combination with params arguments. A params argument allows us to pass a variable amount of arguments at the end of an invocation. The compiler then automatically converts the tail of arguments into an array of the given type. With C# 7.2, we now can add argument names before params arguments. But still, argument names cannot be added for params arguments themselves:

With dynamic invocations, we are unfortunately out of luck. We still cannot use named arguments preceding positional arguments:

For quite some time already, ReSharper has provided code inspections and code style options to make a clear decision. They are located under Options | Code Editing | C# | Code Style. Based on the argument kind, we can choose if an argument should be positional or named. For instance, is it a literal value (true, null, numbers etc.) or string literal value ("Joe")? Is it a named expression (variable, property, etc.) or an anonymous method (lambda expression)? The category Other includes all other expression types, like conditional, null-coalescing, binary, invocation or typeof expressions.

Setting inspections severities and code style for different argument kinds

Tip: we can freely choose to which settings layer these code styles should be saved.

As soon as all settings are in place, code inspections will kick in whenever our settings are not followed. We can then use the corresponding quick-fix (even in bulk mode):

Using quick-fixes to fix code inspections

Users of code cleanup will surely like that we can also activate the option Apply argument style in our code cleanup profile. If applied to the default profile, we just need to invoke the SilentCleanupCode action (Ctrl+E, F):

Using code-cleanup to fix code inspections

As we’ve seen, named arguments can be very helpful to make our code more readable, and with non-trailing named arguments this becomes even more a pleasure. ReSharper 2018.1 EAP is ready on the starting blocks, helping us to apply this new language feature successfully in our code bases.

Download ReSharper 2018.1 EAP now! We’d love to hear your feedback!

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

4 Responses to Non-trailing named arguments in ReSharper 2018.1 EAP

  1. Jeremy Morton says:

    I really like having this, and I want to turn a warning to specify the argument name for literals, but in our async code, we have a lot of

    .ConfigureAwait(continueOnCapturedContext: false);

    at the end of calls to async functions that we await. We really don’t need to have “continueOnCapturedContext:” specified on each call, and it gets really long and unwieldy.

    I wonder if we could disable it for all calls to a specific method, or for a method that only takes one parameter, as it’s usually much clearer what a single bool parameter means, such as in this case.

  2. Pingback: ReSharper Ultimate 2018.1 リリース! | JetBrains ブログ

Leave a Reply

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