CodeQL documentation

Recursive call to operator==

ID: cs/recursive-operator-equals-call
Kind: problem
Severity: error
Precision: medium
Tags:
   - reliability
   - maintainability
Query suites:
   - csharp-security-and-quality.qls

Click to see the query in the CodeQL repository

When writing an operator==, it is common to want to check whether or not an operand is null or check if both operands refer to the same object. Attempting to do this using == will not work as it will simply call the overridden operator== that is being defined.

Recommendation

There are two suggested ways to fix the problem. The tidiest approach is to simply replace the call to operator== with a call to ReferenceEquals (see code below). As a less preferable alternative, it is also possible to simply cast the parameters to object .

Example

In this example the == overload will constantly call itself to compare the initial arguments passed to it with null.

class Year
{
    private int year;
    private bool bc;

    public Year(int i)
    {
        year = Math.Abs(i);
        bc = i < 0;
    }

    public static bool operator ==(Year lhs, Year rhs)
    {
        // Both of these checks against null call operator== recursively.
        // They were probably intended to be checks for reference equality.
        if (lhs == null || rhs == null)
        {
            return false;
        }

        return lhs.year == rhs.year && lhs.bc == rhs.bc;
    }

    public static bool operator !=(Year lhs, Year rhs)
    {
        return !(lhs == rhs);
    }
}

The best fix is to use the ReferenceEquals method instead.

class Year
{
    private int year;
    private bool bc;

    public Year(int i)
    {
        year = Math.Abs(i);
        bc = i < 0;
    }

    public static bool operator ==(Year lhs, Year rhs)
    {
        // Either of these alternative approaches works.
        if (ReferenceEquals(lhs, null) || (object)rhs == null)
        {
            return false;
        }

        return lhs.year == rhs.year && lhs.bc == rhs.bc;
    }

    public static bool operator !=(Year lhs, Year rhs)
    {
        return !(lhs == rhs);
    }
}