13.9 Checking for null References; Introducing C# 6’s ?. Operator

In Section 13.6, we showed the following code snippet:


                       {
                             var exampleObject = new ExampleClass();
                             try
                             {
                                exampleObject.SomeMethod();
                             }
                             finally
                             {
                                if (exampleObject != null)
                                {
                                   exampleObject.Dispose();
                                }
                             }
                       }

The if statement in the preceding finally block ensures that if exampleObject is null, the call to Dispose is skipped, thus preventing a NullReferenceException.

Error-Prevention Tip 13.6

Always ensure that a reference is not null before using it to call a method or access a property of an object.

13.9.1 Null-Conditional Operator (?.)

6 C# 6’s new null-conditional operator (?.) provides a more elegant way to check for null. The following statement replaces the four-line if statement above:


exampleObject?.Dispose();

In this statement, Dispose is called only if exampleObject is not null—exactly as in the preceding if statement.

13.9.2 Revisiting Operators is and as

In Section 12.5.6, we introduced downcasting with the is operator and mentioned that downcasting can cause InvalidCastExceptions. We then mentioned that you can avoid the InvalidCastException by using the as operator as follows:


var employee = currentEmployee as BasePlusCommissionEmployee;

If currentEmployee is a BasePlusCommissionEmployee, employee is assigned the Base-PlusCommissionEmployee; otherwise, it’s assigned null. Since employee could be null, you must ensure that it’s not null before using it. For example, to give the BasePlusCommissionEmployee a 10% raise, we could use the statement


employee?.BaseSalary *= 1.10M;

which accesses and modifies the BaseSalary property only if employee is not null.

13.9.3 Nullable Types

Suppose you’d like to capture the value of the expression employee?.BaseSalary, as in


decimal salary = employee?.BaseSalary;

This statement actually results in a compilation error indicating that you cannot implicitly convert type decimal? to type decimal.

Normally a value-type variable cannot be assigned null. Because the employee reference might be null, the expression


employee?.BaseSalary

returns a nullable type—a value type that also can be null. You specify a nullable type by following a value type’s name with a question mark (?)—so decimal? represents a nullable


decimal? salary = employee?.BaseSalary;

indicates that salary either will be null or the employee’s BaseSalary.

Nullable types have the following capabilities for accessing their underlying values:

  • The GetValueOrDefault method checks whether a nullable-type variable contains a value. If so, the method returns that value; otherwise, it returns the value type’s default value. An overload of this method receives one argument that enables you to specify a custom default value.

  • The HasValue property returns true if a nullable-type variable contains a value; otherwise, it returns false.

  • The Value property returns the nullable-type variable’s underlying value or throws an InvalidOperationException if the underlying value is null.

Variables of nullable types also may be used as the left operand of the null-conditional operator (?.) or the null coalescing operator (??—discussed in the next section).

Error-Prevention Tip 13.7

Before using a nullable-type variable’s Value property, use the HasValue property to check whether the variable has a value. If the nullable-type variable is null, accessing Value results in an InvalidOperationException.

13.9.4 Null Coalescing Operator (??)

C# also offers the null coalescing operator (??) for working with values that can be null. The operator has two operands. If the left operand is not null, the entire ?? expression evaluates to the left operand’s value; otherwise, it evaluates to the right operand’s value. For example, in the statement


decimal salary = employee?.BaseSalary ?? 0M;

if employee is not null, salary is assigned the employee’s BaseSalary; otherwise, salary is assigned 0M. The preceding statement is equivalent to


decimal salary = (employee?.BaseSalary).GetValueOrDefault();

As you can see, the preceding statements are more elegant and more compact than writing the following equivalent code, which must explicitly test for null:


                       decimal salary = 0M;

                       if (employee != null)
                       {
                          salary = employee.BaseSalary
                       }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset