Equals Signature Correct

ID

csharp.equals_signature_correct

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

CWE:581, equals, reliability

Description

Reports Equals methods whose signature deviates from the canonical public override bool Equals(object obj). The rule flags overrides whose parameter type is not object (which do not actually override System.Object.Equals) and instance Equals methods whose return type is not bool.

Rationale

C# resolves overrides by exact parameter type, so public override bool Equals(MyType other) silently fails to override object.Equals(object). Hash-based collections still call the base reference-identity comparison, and the developer’s intended equality logic is bypassed. Likewise, an Equals method that returns anything other than bool cannot participate in the IEquatable<T> or object.Equals contract.

public class Money
{
    public override bool Equals(Money other)        // FLAW — wrong parameter type
        => other != null && other.Amount == Amount;

    public int Equals(object obj)                   // FLAW — wrong return type
        => obj is Money m && m.Amount == Amount ? 1 : 0;
}

public class MoneyOk
{
    public override bool Equals(object obj)         // OK
        => obj is MoneyOk m && m.Amount == Amount;
}

Remediation

Use the canonical signature public override bool Equals(object obj) when overriding System.Object.Equals. If you also want a strongly-typed comparison, implement IEquatable<T> and add a separate bool Equals(T other) method that the override delegates to. Always pair the override with GetHashCode.