[818] Equality Generation Question

I have a new class and have used Alt + Ins and Equality Members to generate a new equality override, operators and IEquatable]]>. The code for the override goes like:

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == typeof(Base) && Equals((Base)obj);
}

Does this not exclude comparison with equivalent types that are subclasses of the base class? Sure, I can't think of a scenario where this would be required...maybe I would move from being a customer to being an employee?!?! However, would not the below be more the way to go?

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return typeof(Base).IsAssignableFrom(obj.GetType()) && Equals((Base)obj);
}

Thanks

Sean

4 comments
Comment actions Permalink

Personally, I could hardly imagine when you should create equality metric on
classes of different type. Generally, this is bug in design.

--
Eugene Pasynkov
Developer
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
"sean kearon" wrote in message news:14338291.62681214848958080.JavaMail.jive@app4.labs.intellij.net... >I have a new class and have used Alt + Ins and Equality Members to generate >a new equality override, operators and IEquatable. The code for the >override goes like: >]]>

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == typeof(Base) && Equals((Base)obj);
}

>

Does this not exclude comparison with equivalent types that are subclasses
of the base class? Sure, I can't think of a scenario where this would be
required...maybe I would move from being a customer to being an
employee?!?! However, would not the below be more the way to go?

>

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return typeof(Base).IsAssignableFrom(obj.GetType()) &&
Equals((Base)obj);
}

>

Thanks

>

Sean



0
Comment actions Permalink

Hi Eugene

My domain classes have equality by Id and descend from an abstract base that implements the Id machinery. This fails to respect equality when using the current generated code.

Cheers

Sean



public void Equality_by_id()
{
var id = Guid.NewGuid();
var instance1 = new TestObject(id);
var instance2 = new TestObject(id);

Assert.IsTrue(instance1.Equals(instance2));
Assert.IsTrue(instance1 == instance2);
Assert.IsFalse(instance1 != instance2);
Assert.IsFalse(ReferenceEquals(instance1, instance2));
Assert.AreEqual(instance1.GetHashCode(), instance2.GetHashCode());
}

internal class TestObject: BaseObject
{
public TestObject(Guid id) : base(id) { }

public TestObject() { }
}

public abstract class BaseObject : IEquatable]]>
{
#region Constructors

protected BaseObject(Guid id)
{
if (id == Guid.Empty)
{
throw new ArgumentOutOfRangeException("id", "Id value not defined.");
}
Id = id;
}

protected BaseObject()
{
Id = Guid.NewGuid();
}

#endregion

#region Operators

public static bool operator ==(BaseObject left, BaseObject right)
{
return Equals(left, right);
}

public static bool operator !=(BaseObject left, BaseObject right)
{
return !Equals(left, right);
}

#endregion

#region Methods

public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == typeof (BaseObject) && Equals((BaseObject) obj);
}

public override int GetHashCode()
{
return Id.GetHashCode();
}

public bool Equals(BaseObject obj)
{
if (ReferenceEquals(null, obj)) return false;
return ReferenceEquals(this, obj) || obj.Id.Equals(Id);
}

#endregion

#region Properties

public Guid Id { get; private set; }

#endregion
}

0
Comment actions Permalink

Hello sean,

We've seen many cases, when equality generated with "as MyType" check for
type equaivalence led to problems in the future. Thus, it was decided to
implement a stronger check. However, I agree there cases when one may need
an "hierarchy-aware" equality checks. But we want it to be concious decision,
rather then something that is decided by ReSharper. If you file request about
it, we will include this into next update of Generate feature.

Sincerely,
Ilya Ryzhenkov

JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


IR> Hi Eugene
IR>
IR> My domain classes have equality by Id and descend from an abstract
IR> base that implements the Id machinery. This fails to respect
IR> equality when using the current generated code.
IR>
IR> Cheers
IR>
IR> Sean
IR>
IR>
IR> public void Equality_by_id()
IR> {
IR> var id = Guid.NewGuid();
IR> var instance1 = new TestObject(id);
IR> var instance2 = new TestObject(id);
IR> Assert.IsTrue(instance1.Equals(instance2));
IR> Assert.IsTrue(instance1 == instance2);
IR> Assert.IsFalse(instance1 != instance2);
IR> Assert.IsFalse(ReferenceEquals(instance1, instance2));
IR> Assert.AreEqual(instance1.GetHashCode(),
IR> instance2.GetHashCode());
IR> }
IR> internal class TestObject: BaseObject
IR> {
IR> public TestObject(Guid id) : base(id) { }
IR> public TestObject() { }
IR> }
IR> public abstract class BaseObject : IEquatable IR> { IR> #region Constructors IR> protected BaseObject(Guid id) IR> { IR> if (id == Guid.Empty) IR> { IR> throw new ArgumentOutOfRangeException("id", "Id value IR> not defined."); IR> } IR> Id = id; IR> } IR> protected BaseObject() IR> { IR> Id = Guid.NewGuid(); IR> } IR> #endregion IR> IR> #region Operators IR> IR> public static bool operator ==(BaseObject left, BaseObject IR> right) IR> { IR> return Equals(left, right); IR> } IR> public static bool operator !=(BaseObject left, BaseObject IR> right) IR> { IR> return !Equals(left, right); IR> } IR> #endregion IR> IR> #region Methods IR> IR> public override bool Equals(object obj) IR> { IR> if (ReferenceEquals(null, obj)) return false; IR> if (ReferenceEquals(this, obj)) return true; IR> return obj.GetType() == typeof (BaseObject) && IR> Equals((BaseObject) obj); IR> } IR> public override int GetHashCode() IR> { IR> return Id.GetHashCode(); IR> } IR> public bool Equals(BaseObject obj) IR> { IR> if (ReferenceEquals(null, obj)) return false; IR> return ReferenceEquals(this, obj) || obj.Id.Equals(Id); IR> } IR> #endregion IR> IR> #region Properties IR> IR> public Guid Id { get; private set; } IR> IR> #endregion IR>]]> }


0

Please sign in to leave a comment.