Equals Unrelated Types

ID

csharp.equals_unrelated_types

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

CWE:597, equals, reliability

Description

Reports the body of Equals(object obj) overrides that test the argument against a type which is neither the enclosing type nor a known primitive. Comparing against an unrelated class is almost always a copy-paste mistake: the override will never decide equality between two instances of the enclosing type correctly.

Rationale

Equals(object) is intended to decide structural equality between two instances of the same conceptual type. Casting or pattern-matching against an unrelated class breaks the contract — the override will return false for two genuine instances of the enclosing type and may unexpectedly return true for instances of the unrelated class.

public class Account
{
    public override bool Equals(object obj)
    {
        return obj is Customer c && c.Id == 0;             // FLAW — tests against unrelated Customer type
    }
}

public class AccountOk
{
    public int Id { get; }

    public override bool Equals(object obj)
    {
        return obj is AccountOk other && other.Id == Id;   // OK
    }
}

Remediation

Test the argument against the enclosing type (typically with obj is MyType other and then compare members). For polymorphic equality across subtypes, use the most specific common base type or IEquatable<T> on the shared base.