overload Equals, is this wrong? - c#

Reading some piece of code and I keep seeing this :
public override bool Equals (object obj)
{
if (obj == null || this.GetType ().Equals (obj.GetType())) return false;
//compare code...
}
Shouldn't it be like this (note the !):
public override bool Equals (object obj)
{
if (obj == null || !this.GetType ().Equals (obj.GetType())) return false;
//compare code...
}
Or does the equals perform differently in this case?

That looks like a bug. Returning false when the types are the same is certainly not the intended behaviour.

Related

How do I override GetHashCode() without any numbers as fields?

All of the resources showing how to override Equals(object) and GetHashCode() use numeric fields to implement the GetHashCode() method:
Implementing the Equals Method
What's the best strategy for Equals and GetHashCode?
Why is it important to override GetHashCode when Equals method is overridden?
However, in my class, I do not have any numeric fields. It is a node in a tree with a reference to its parent, children, and an interface as the data:
public class Node
{
private IInterface myInterface;
private Node parent;
private List<Node> children = new List<Node>();
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var node = (Node)obj;
return myInterface == node.myInterface;
}
public override int GetHashCode()
{
???
}
}
What should I set the hashcode with?
According to Equals implementation, two Nodes instances are equal if and only if their myInterface are equal:
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var node = (Node)obj;
// instances are equal if and only if myInterface's are equal
return myInterface == node.myInterface;
}
That's why myInterface is the only source for GetHashCode:
public override int GetHashCode()
{
return null == myInterface ? 0 : myInterface.GetHashCode();
}
P.S. (Edited, thanks to Kris Vandermotten) Often, it's a good practice to check for ReferenceEquals in the Equals implementation before comparing potentially time/resource consuming myInterfaces:
public override bool Equals(object obj) {
// Easy tests:
// 1. If "this" and "obj" are in fact just the same reference?
// 2. Since `Node` (or Equals) is not sealed, the safiest is to check types
if (object.ReferenceEquals(this, obj))
return true;
else if (null == obj || other.GetType() != GetType())
return false;
// Potentially time/resource cosuming (we don't know IInterface implementation)
return ((Node) obj).myInterface == myInterface;
}

Warning: Object defines operator == or operator != but does not override Object.Equals(object o)

I'm programming in C# Unity and have really annoying problem - I want to define special Pair class with following relations:
public class Pair<T1>{
public int First;
public T1 Second;
public bool Equals(Pair<T1> b){
return First == b.First;
}
public static bool operator==(Pair<T1> a, Pair<T1> b){
return a.First == b.First;
}
public static bool operator!=(Pair<T1> a, Pair<T1> b){
return a.First != b.First;
}
}
Which gives me following warning:
Warning CS0660: 'Pair' defines operator == or operator != but does
not override Object.Equals(object o) (CS0660) (Assembly-CSharp)
But also when I spawn two objects of Pair type with same First integer, their == operator returns True (as I want). When I only declare Equals function, same == operator returns False value (I understand that somehow Unity compares their addressees in memory), with no warnings. Is there any method to avoid warnings and still get True value of == operator?
Just override that method to make the compiler happy :
public override bool Equals(object o)
{
if(o == null)
return false;
var second = o as Pair<T1>;
return second != null && First == second.First;
}
public override int GetHashCode()
{
return First;
}
The method you created is a custom equals method, you need to override that of the object class (which is used in the == && != operators)
You need to override the Equal:
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Pair<T1>) obj);
}
And the GetHashCode method:
public override int GetHashCode()
{
unchecked
{
return (First*397) ^ EqualityComparer<T1>.Default.GetHashCode(Second);
}
}

LINQ to Object Join operator and equality

I have the following simple LINQ to Object query:
var accountsWithOpportunities = (from a in accountGetServices
join o in opportunities on a equals o.Account
select a).ToList();
This query always 0 results but this query does not:
var accountsWithOpportunities = (from a in accountGetServices
join o in opportunities on a.Id equals o.Account.Id
select a).ToList();
Therefor, I reached to the conclusion that my equality operation is doing something wrong.
I have the following abstract class that is being used for all models:
public abstract class BaseModel<T> : BaseModel
where T : class, IIdentifyable
{
public static bool operator ==(BaseModel<T> c1, BaseModel<T> c2)
{
T t1 = c1 as T;
T t2 = c2 as T;
if (object.ReferenceEquals(t1, t2)) return true;
if (object.ReferenceEquals(t1, null)) return false;
if (object.ReferenceEquals(t2, null)) return false;
return c1.Equals(c2);
}
public static bool operator !=(BaseModel<T> c1, BaseModel<T> c2)
{
return !(c1 == c2);
}
}
public abstract class BaseModel : IEquatable<BaseModel>
{
public bool Equals(BaseModel other)
{
if (other == null)
return false;
var identifyable1 = this as IIdentifyable;
var identifyable2 = other as IIdentifyable;
return identifyable1.Id == identifyable2.Id;
}
public override bool Equals(object obj)
{
return base.Equals(obj) && Equals(obj as BaseModel);
}
}
I placed breakpoints on each function to see what goes on under the hood but none of them are hit.
What am I doing wrong?
public override bool Equals(object obj)
{
return base.Equals(obj) && Equals(obj as BaseModel);
}
This part seems to be wrong. base.Equals calls object.ReferenceEquals which always (or at least in most of the cases) returns false and therefore the other expression is never evaluated.
EDIT
Also, as you pointed out earlier, GetHashCode gets called (you should get a compiler warning that you've overridden Equals but not GetHashCode). So change the GetHashCode to return the Id of the entity and it should start working.
Is public override bool Equals(object obj) not being hit? I see you are calling object.Equals here which would make it always return false. A better implementation would be:
public override bool Equals(object obj)
{
return this.Equals(obj as BaseModel);
}
The real solution is to override GetHashCode() to always return 0.
Then all the equality functions are being hit.
I'm not sure why or if there's a better way to implement GetHashCode().

GetHashCode Equality

I've wondered about this, so I figure I'll ask it.
Most places you'll see use the same semantic logic for overriding Equals as GetHashCode for memberwise equality...however they usually use different implementations:
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
var other = (MyType)obj;
if (other.Prop1 != Prop1)
{
return false;
}
return true;
}
public override int GetHashCode()
{
int hash = -657803396;
num ^= Prop1.GetHashCode();
return num;
}
If you're implementing memberwise equality for your type (lets say for storing in a dictionary), why not just override GetHashCode then do something like this for Equals:
public override bool Equals(object obj)
{
return this.HashEqualsAndIsSameType(obj);
}
public static bool HashEquals(this object source, object obj)
{
if (source != null && obj != null)
{
return source.GetHashCode() == obj.GetHashCode();
}
if (source != null || obj != null)
{
return false;
}
return true;
}
public static bool HashEqualsAndIsSameType<T>(this T source, object obj)
{
return (obj == null || obj.GetType() == typeof(T)) && source.HashEquals(obj);
}
Because there is a real risk of conflicts. Hash-codes are not unique. They can (when different) prove inequality, but never equality. When looking for an item:
get the hash-code(s)
if the hash-code is different, the object is different; discard it
if the hash-code is the same, check Equals:
if Equals reports true they are the same
else discard
Consider long... since hash-code is int, it is easy to see that there are lots and lots of conflicts.
Hashes are not 1-to-1, you can have multiple different values that hash to the same value, but which should compare as not equal. So you cannot really implement Equals in terms of GetHashCode. This is why you have collisions in a hash table, and why a hash table lookup must involve call(s) to both GetHashCode and Equals.

C# - Any Code optimization technique for Overriding "Equals"?

Normally ( Based on my understanding ) i have to follow a lot of steps to
override the "Equals" to check the state of the object.
Example :
public override bool Equals(object obj)
{
if (obj is SalesPerson && obj != null)
{
SalesPerson temp;
temp = (SalesPerson)obj;
if (temp.fName == this.fName && temp.lName == this.fName
&& temp.personAge == this.personAge )
{
return true;
}
else
{
return false;
}
}
return false;
}
Any other alternative like LINQ or other techniques gives me shortcut code ?
Update :
Moreover i gusess i have to override GetHasCode() too when i override "Equals".
All the answers so far seem mostly fine to me. However, you should carefully consider what you want equality to mean in an inheritance hierarchy. Can an instance of just SalesPerson be equal to an instance of SalesManager (which would derive from SalesPerson)?
The trouble is, the symmetric nature of equals gets in the way. Suppose we have:
SalesPerson x = new SalesPerson { ... };
SalesManager y = new SalesManager { ... };
I'd expect y.Equals(x) to be false - which means that x.Equals(y) ought to be false too.
This means the check in SalesPerson really needs to be:
public override bool Equals(object obj)
{
SalesPerson salesPerson = obj as SalePerson;
if (salesPerson == null) return false;
return salesPerson.GetType() == this.GetType() &&
salesPerson.fName == this.fName &&
salesPerson.lName == this.fName &&
salesPerson.personAge == this.personAge;
}
Note that I'm not comparing with typeof(SalesPerson) as the implementation in SalesManager would probably want to call up to this implementation first.
Of course, all of this complication goes away if SalesPerson is sealed... another reason for being very careful before introducing inheritance :)
This looks neater:
public override bool Equals(object obj)
{
SalesPerson salesPerson = obj as SalePerson;
if(salesPerson == null) return false;
return salesPerson.fName == this.fName &&
salesPerson.lName == this.fName &&
salesPerson.personAge == this.personAge;
}
And of course if you really wanted to compact it into a single line you could use:
public override bool Equals(object obj)
{
SalesPerson salesPerson = obj as SalePerson;
return (salesPerson != null) &&
(salesPerson.fName == this.fName &&
salesPerson.lName == this.fName &&
salesPerson.personAge == this.personAge);
}
The test for non-null is guaranteed to run first and therefore no potential NullReferenceException can occur in the rest of the equality test.
You code seems very overcomplicated. I'd replace it with this:
public override bool Equals(object obj)
{
SalesPerson temp = obj as SalesPerson;
if(temp == null) return false;
return temp.fName == this.fName && temp.lName == this.fName
&& temp.personAge == this.personAge;
}
You could then write some operators == != etc..
I recommend to use the reflector tool and learn best practices directly from Microsoft's code.
For example, System.Reflection.Module class equals function implementation:
public override bool Equals(object o)
{
if (o == null)
{
return false;
}
if (!(o is Module))
{
return false;
}
Module internalModule = o as Module;
internalModule = internalModule.InternalModule;
return (this.InternalModule == internalModule);
}
EDIT: Changed the implementation example to Module class.
I find Resharper a very useful tool for 'drudge' work such as this, and can certainly help you focus on what you are trying to achieve over the implementation detail.
See here for more info. If there are alternatives I'm open to hear them.

Categories