Null checking improvements in ReSharper 2017.2

Null checking is a very common task that ReSharper has always been helping to automate. Since the very first versions, ReSharper users had a whole bunch of context actions and quick-fixes at their disposal, such as Check parameter for null, Assert expression is not null and Check variable for null.

As we’re constantly improving the coding experience, we made a number of changes in previous releases: we extended the Check parameter for null action to check all parameters at once and also added an option to insert null checks when generating a constructor. ReSharper 2017.2 advances null checking even further. Let’s see!

Null checking preferences

There are plenty of ways to perform a null check in C#: classic “if-then-throw”, “if-then-throw” with ReferenceEquals call, using different kinds of assertions — including ones from BCL, from Code Contracts library or user-defined helpers, … Not to mention that C# 7.0 adds two more with throw expressions and pattern matching.

Until now ReSharper supported only the classic pattern. The new release removes this limitation by introducing a new options page, where you can configure null checking preferences!

You can find the Null checking page in ReSharper | Options | Code Editing | C# section, or directly from the Check parameter for null context action. It has a new menu entry, Configure null-check pattern, which helps you access this new page without digging through the dialog.

The options page lists all predefined null checking patterns in the priority order — with higher priority patterns shown at the top. The order can be changed using Move up(Alt+U) and Move down(Alt+D) buttons. When ReSharper generates a null check, it will take the highest-priority pattern which semantically suits the context, taking into account the current C# version.

Consider the following example:

In the first case, ReSharper uses the Throw expression pattern because it has the highest priority by default. But in the second case, there is no assignment from a parameter in question, so ReSharper tries to apply the next pattern, Classic, which always succeeds.

Mind that only a subset of null checking patterns can be used by the Assert expression is not null quick-fix. For instance, Debug assert pattern is suitable for assertion while the Classic one isn’t. The Null checking options page displays whether the pattern can be used for assertion and in case of custom patterns allows to change this setting.

Using custom null check helper methods

Now let’s see how we can configure ReSharper to use custom helper methods. Suppose we have the following class:

$"Value of type '{typeof(T).FullName}' is null at {memberName}, {filePath}:{lineNumber}");

}

}

}

The AssertionMethod and AssertionCondition attributes mark the methods and parameters. They provide a hint to ReSharper’s code analysis engine, that if the method call completes without exception, the value parameter cannot be null. You can learn more about JetBrains Annotations here.

We’d like to use the AssertNotNull method in a statement context and NotNull in expression context (since it is an extension method, invocation can be inserted right in place.)

In order to do so, first we should go to Null checking options page, and edit Custom (statement) and Custom (expression) patterns in the following way:

Notice that patterns use the fully qualified class name Utils.Assertion, not simply Assertion. That’s because we want ReSharper to correctly resolve the method and insert required using directives when needed.

As patterns are customized we should increase their priority using the Move up button (expression-based pattern should be on top). After that, we are ready to use them!

Typing assistance with ! and ?

ReSharper 2017.2 comes with another feature that makes it easier to check parameters for null values. Inspired by languages like Kotlin and Swift, where nullable and non-nullable reference types have a clear distinction, we made typing ! or ? after a type or name in parameter declaration (or any other member declaration) insert a [NotNull] or [CanBeNull] annotation.

More than that, if parameter is already marked with [NotNull], typing ! will automatically add a null check. Note that this feature requires the presence of JetBrains Annotations in project.

It’s a little too early to talk about, as design of nullable reference types is only getting shaped, but yes, we’re definitely thinking about providing feature like this. People who use JetBrains Annotations will benefit when it comes to migration.

There seems to be a lot of bogus warnings with the new version particularly for intptrs. These can never be null but R# now underlines every single one and said it can be null. You can’t even compare them with null so how do you get rid of the warnings?

Oh not to mention that it is a lot more buggy than one version ago. Auto parentheses termination cuts off at the wrong index. Very amateurish update to be honest. Haven’t seen am update so bad since when R# first started.