Back to Devexpress

Null Reference Analysis

coderushforroslyn-401603-static-code-analysis-null-reference-analysis.md

latest8.8 KB
Original Source

Null Reference Analysis

  • Feb 03, 2021
  • 5 minutes to read

CodeRush includes the CRR0027 - Possible System.NullReferenceException analyzer. This analyzer detects unprotected code that can potentially raise a System.NullReferenceException exception.

To enable this analyzer, choose the Possible System.NullReferenceException issue in the Editor | Language | Code Analysis | Code Issues Catalog options page, check the Enabled checkbox, and click OK.

You can analyze a solution, an active project, or an active document in the Code Issues window. To invoke this window, open the CodeRush menu and choose the Code Analysis | Code Issues menu item.

Note

CodeRush menu is placed in the Visual Studio Extensions menu for Visual Studio 2019. You can restore the default CodeRush menu position in Visual Studio 2019 16.4 or later. See the First Steps topic for more information.

In the Code Issues window, click the Refresh button to start code analysis.

Null Reference Analysis Modes

CodeRush can analyze values in Trusting , Skeptical , and Thorough diagnostic modes. You can specify the Possible System.NullReferenceException diagnostic mode for methods, properties, parameters, fields, and local variables in the Editor | Language | Code Analysis | Possible NullReferenceException options page.

The following sections describe each diagnostic mode:

Trusting

If an element is not checked for null in the current scope and does not have the [CanBeNull] attribute, the analyzer trusts this element and does not show the diagnostic in the Code Issues window.

In the example below, the SortElements method does not provide information whether Elements are null or not. The Possible System.NullReferenceException analyzer considers Elements as not null in Trusting mode and does not show the diagnostic in the Code Issues window.

csharp
class TrustingMode {
    public List<string> Elements { get; set; }

    public void SortElements() {
        Elements.Sort();
    }
}
vb
Class TrustingMode
    Public Property Elements As List(Of String)

    Public Sub SortElements()
        Elements.Sort()
    End Sub
End Class

The analyzer shows the CRR0027 - Possible System.NullReferenceException diagnostic in Trusting mode, for example, if the following code has a null check error:

csharp
class TrustingMode {
    public List<string> Elements { get; set; }

    public void SortElements() {
        if (Elements == null)
            Elements.Sort();
    }
}
vb
Class TrustingMode
    Public Property Elements As List(Of String)

    Public Sub SortElements()
        If Elements Is Nothing Then Elements.Sort()
    End Sub
End Class

The Code Issues window looks as follows:

You can mark the Elements property with the [CanBeNull] code annotation attribute to indicate this property can be null.

csharp
class TrustingMode {
    [CanBeNull]
    public List<string> Elements { get; set; }

    public void SortElements() {
        Elements.Sort();
    }
}
vb
Class TrustingMode
    <CanBeNull>
    Public Property Elements As List(Of String)

    Public Sub SortElements()
        Elements.Sort()
    End Sub
End Class

In this case, the analyzer shows the diagnostic even if the code does not have a null check expression.

Skeptical

If an element is not checked for null in the current scope, the analyzer does not show the diagnostic for elements that have the [NotNull] attribute.

In the example below, the Elements property is not checked for null.

csharp
class SkepticalMode {
    public List<string> Elements { get; set; }

    public int GetEmptyElementCount() {
        var count = 0;

        foreach (var element in Elements) {

            if (string.IsNullOrEmpty(element))
                count++;
        }
        return count;
    }
}
vb
Class SkepticalMode
    Public Property Elements As List(Of String)

    Public Function GetEmptyElementCount() As Integer
        Dim count = 0

        For Each element In Elements
            If String.IsNullOrEmpty(element) Then count += 1
        Next

        Return count
    End Function
End Class

The analyzer shows the diagnostic for the Elements property in this case:

If you do not want the analyzer to show this diagnostic, add the null check.

csharp
class SkepticalMode {
    public List<string> Elements { get; set; }

    public int GetEmptyElementCount() {
        var count = 0;

        if (Elements == null)
            return 0;

        foreach (var element in Elements) {

            if (string.IsNullOrEmpty(element))
                count++;
        }
        return count;
    }
}
vb
Class SkepticalMode
    Public Property Elements As List(Of String)

    Public Function GetEmptyElementCount() As Integer
        Dim count = 0
        If Elements Is Nothing Then Return 0

        For Each element In Elements
            If String.IsNullOrEmpty(element) Then count += 1
        Next

        Return count
    End Function
End Class

You can also use the [NotNull] code attribute to indicate the Elements property is not null.

csharp
class SkepticalMode {

    [NotNull]
    public List<string> Elements { get; set; }

    public int GetEmptyElementCount() {
        var count = 0;        

        foreach (var element in Elements) {

            if (string.IsNullOrEmpty(element))
                count++;
        }
        return count;
    }
}
vb
Class SkepticalMode
    <NotNull>
    Public Property Elements As List(Of String)

    Public Function GetEmptyElementCount() As Integer
        Dim count = 0

        For Each element In Elements
            If String.IsNullOrEmpty(element) Then count += 1
        Next

        Return count
    End Function
End Class

Thorough

If an element is not checked for null in the current scope and the element does not have the [CanBeNull] or [NotNull] attribute, the analyzer checks if the element can never be null (lazy initialized, returns new created object, etc). The mode works more slowly than others.

In the following code, the analyzer shows the diagnostic in Skeptical mode but does not show it in Thorough mode because the Elements property always returns a non-null value.

csharp
class ThoroughMode {

    List<string> elements;

    public List<string> Elements {

        get

        {   
            if (elements == null)
                elements = new List<string>();
            return elements;
            }
        }

    public int GetEmptyElementCount() {

        var count = 0;

        foreach (var element in Elements) {

            if (string.IsNullOrEmpty(element))

                count++;
        }
        return count;
    }
}
vb
Class ThoroughMode
    Private elements As List(Of String)

    Public ReadOnly Property Elements As List(Of String)
        Get
            If elements Is Nothing Then elements = New List(Of String)()
            Return elements
        End Get
    End Property

    Public Function GetEmptyElementCount() As Integer
        Dim count = 0

        For Each element In Elements
            If String.IsNullOrEmpty(element) Then count += 1
        Next

        Return count
    End Function
End Class

Annotation Attributes

CodeRush checks annotation attributes by a partial name. This means you do not need to reference annotations, just declare them in code.