rspec/rules/S3397/rule.adoc

80 lines
1.7 KiB
Plaintext

== Why is this an issue?
``++object.Equals()++`` overrides can be optimized by checking first for reference equality between ``++this++`` and the parameter. This check can be implemented by calling ``++object.ReferenceEquals()++`` or ``++base.Equals()++``, where ``++base++`` is ``++object++``. However, using ``++base.Equals()++`` is a maintenance hazard because while it works if you extend ``++Object++`` directly, if you introduce a new base class that overrides ``++Equals++``, it suddenly stops working.
This rule raises an issue if ``++base.Equals()++`` is used but ``++base++`` is not ``++object++``.
=== Noncompliant code example
[source,text]
----
class Base
{
private int baseField;
public override bool Equals(object other)
{
if (base.Equals(other)) // Okay; base is object
{
return true;
}
return this.baseField == ((Base)other).baseField;
}
}
class Derived : Base
{
private int derivedField;
public override bool Equals(object other)
{
if (base.Equals(other)) // Noncompliant
{
return true;
}
return this.derivedField == ((Derived)other).derivedField;
}
}
----
=== Compliant solution
[source,text]
----
class Base
{
private int baseField;
public override bool Equals(object other)
{
if (object.ReferenceEquals(this, other)) // base.Equals is okay here, but object.ReferenceEquals is better
{
return true;
}
return this.baseField == ((Base)other).baseField;
}
}
class Derived : Base
{
private int derivedField;
public override bool Equals(object other)
{
if (object.ReferenceEquals(this, other))
{
return true;
}
return base.Equals(other) && this.derivedField == ((Derived)other).derivedField;
}
}
----