Konrad Viltersten
Konrad Viltersten

Reputation: 39118

Why is the input parameter of Equals of type Object?

I've overridden Equals(Object input) thousands of times and never contemplated the matter deeper. Now, after a few drink, I started to think about it and it stroke me that I'm not entirely certain why it's so.

Equality operation is semantically speaking checking if two thingies are a copy of itself. Generally, it's done based on the pointer (reference value or whatever one might want to call it). On occasion, we'd like to define the equality as e.g. sum of some properties of instance a being the same as that of instance b, not necessarily being equal on any of them.

However, two objects of different type can't have the same reference, can they? And, even if two type have the same set of properties, called the same, typed the same, it's still apples and oranges, so the comparison will be either meaningless (at the very least) or darn damaging to the logic.

Is there any (and I mean any at all) occasion where the input to the operation of Equals might be of different type then the comparee and still make sense?

Upvotes: 2

Views: 132

Answers (1)

Jcl
Jcl

Reputation: 28272

Your assumptions are wrong:

Equality operation is semantically speaking checking if two thingies are a copy of itself. Generally, it's done based on the pointer (reference value or whatever one might want to call it).

That's Reference equality and it's checked by the function Object.ReferenceEquals (which is static and not overridable)

Object equality is different, and you can apply the rules you want to it. In case it wasn't like that, how would you check two value types (which cannot hold the same reference in C#) for equality?

Consider:

int a = 5;
int b = 5;
a.Equals(b); // what would this return? `a` and `b` are different objects

Now for the second part of your question, there are objects that, depending on your needs, may need to be considered equal being of different types. Consider:

public class Point2D {
  public int X, Y;
}

public class Point3D {
  public int X, Y, Z;

  public override bool Equals(object source) {
    var p2D = source as Point2D;
    if(p2D != null)
    {
      if(this.Z == 0 && p2D.X == this.X && p2D.Y == this.Y)
        return true;
      return false;
    }
    //...
  }
}

In this case:

var p2D = new Point2D(5,5);  // <-- let's pretend we have the right constructor  
var p3D = new Point3D(5,5,0);
object.Equals(p3D,p2D); // <-- returns true
object.ReferenceEquals(p3D, p2D); // <-- returns false

For performance (specially for value types), you may want to implement IEquatable<T> or IEqualityComparer<T> (or better yet, derive from EqualityComparer<T>), which allows for a direct comparison to a specific type (without having to box it to object before), but that's outside the scope of this answer.

Note that it's still recommended to override Object.Equals if you implement this interface so that the behaviour is matched between the two.

Upvotes: 7

Related Questions