EqualsNull

EqualsNull

Summary

Use “… is null” or “… is {}” instead of “… == null.”

Default severity

Info

Description

This rule reports diagnostic information of using the equality operators (“==” and “!=”) with null as follows:

  • The operator is either “==” or “!=.”
  • The right operand is null.
  • The type of the left operand is not a non-nullable value type. (If it is a non-nullable value type, the compiler raises CS0472 and the expression is always true or false.)

Note that the default diagnostic severity of this analyzer is Information.

Code fix

The code fix provides an option replacing the expressions “… == null” and “… != null” with “… is null” and “!(… is null),” respectively. Also, it provides another option replacing them with “!(… is {})” and “… is {},” respectively.

Remarks

It can be a breaking change to replace the expression “… == null” with “… is null,” as well as “… != null” with “!(… is null),” and vice versa. For example, the expressions “o is null” and “o == null” result in the same IL code as long as its equality operators are not overridden, as follows:

class C
{
    bool IsNull(C o) => o is null;
    /*
        IL_0000: ldarg.1
        IL_0001: ldnull
        IL_0002: ceq
        IL_0004: ret
    */

    bool EqualsNull(C o) => o == null;
    /*
        IL_0000: ldarg.1
        IL_0001: ldnull
        IL_0002: ceq
        IL_0004: ret
    */
}

However, when its equality operators are overridden, those expressions result in different IL codes, as follows:

class C
{
    bool IsNull(C o) => o is null;
    /*
        IL_0000: ldarg.1
        IL_0001: ldnull
        IL_0002: ceq
        IL_0004: ret
    */

    bool EqualsNull(C o) => o == null;
    /*
        IL_0000: ldarg.1
        IL_0001: ldnull
        IL_0002: call bool C::op_Equality(class C, class C)
        IL_0007: ret
    */

    public static bool operator== (C o1, C o2)
        => object.ReferenceEquals(o1, o2);

    public static bool operator!= (C o1, C o2)
        => !object.ReferenceEquals(o1, o2);
}

Note that the result of “o == null” may differ from the one of “o is null” if the equality operators are strangely overridden as follows:

class C
{
    ⋮
    public static bool operator== (C o1, C o2) => true;
    public static bool operator!= (C o1, C o2) => false;
}

Example

Diagnostic

public void Method(object? o, string? s)
{
    if (o == null && s != null)
    {
        ⋮
    }
    ⋮

Code fix (with the constant pattern)

public void Method(object? o, string? s)
{
    if (o is null && !(s is null))
    {
        ⋮
    }
    ⋮

Code fix (with the property pattern)

public void Method(object? o, string? s)
{
    if (!(o is {}) && s is {})
    {
        ⋮
    }
    ⋮