Refactoring ternary expressions into null-coalescing operations and vice versa
There are two interesting refactorings shipped in Refactor! Pro:
- Compress to Null Coalescing Operation
- Expand Null Coalescing Operation
The first one converts a ternary expression into an equivalent null coalescing operation. The second one is the opposite of the first one – it converts a null coalescing operation to an equivalent ternary expression. Both refactorings are available in CSharp only, because Visual Basic, for example, doesn’t have a null coalescing operator.
Here’s an excerpt from the C# language specification about the null coalescing operator for reference:
- A null coalescing expression of the form a ?? b requires a to be of a nullable type or reference type. If a is non-null, the result of a ?? b is a; otherwise, the result is b. The operation evaluates b only if a is null.
- The null coalescing operator is right-associative, meaning that operations are grouped from right to left. For example, an expression of the form a ?? b ?? c is evaluated as a ?? (b ?? c). In general terms, an expression of the form E1 ?? E2 ?? … ?? EN returns the first of the operands that is non-null, or null if all operands are null.
So, the null coalescing operator provides an effective, compact way to check whether a value is null, and if so, return an alternative value. For example:
Brush myBrush = GetCachedBrush() ?? new SolidBrush(Color.Black);
In the code above, if the return value of GetCachedBrush() is not null, it is assigned to the myBrush variable. Otherwise, if it is null, a new SolidBrush is created and assigned.
The ?? operator is also useful for output. For example, instead of using the ternary operator,
String userName = GetUserName(); Console.WriteLine(userName != null ? userName : "User doesn't exist.");
You can apply the Compress to Null Coalescing Operation refactoring:
(click on the image to see it in the original size)
and use the null coalescing operator instead:
String userName = GetUserName(); Console.WriteLine(userName ?? "User doesn't exist.");
The Expand Null Coalescing Operation can be useful when you would like to change the condition of the check, for example. From a null check to something different, e.g.:
Console.WriteLine(userName != String.Empty ? userName : "User name is undefined.");
The preview hint of the refactoring will show you the resulting code before you apply it:
(click on the image to see it in the original size)
—– Products: Refactor! Pro Versions: 10.2 and up VS IDEs: any Updated: May/26/2011 ID: R028