GetHashCode Equality - c#

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.

Related

C# list of custom class .Contains()

i have a list of custom class and before adding to the list i want to check if the list has the same instance (not one attribute - all of them)
public class Function
{
public string Name;
public string RT;
public int ParamCount;
public List<string> ParamDT;
public Function()
{
ParamDT = new List<string>();
}
}
i tried overriding Equals() and GetHashCode()
but it didn't work
Equals()
public override bool Equals(object obj)
{
var item = obj as Function;
if (item == null)
{
return false;
}
return this.Name == item.Name && this.RT == item.RT &&
this.ParamCount == item.ParamCount && this.ParamDT.Equals(item.ParamDT);
}
GetHashCode()
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
ParamDT is also a list, you have to check its items also individually to compare properly.
this.ParamDT.Equals(item.ParamDT);
Having said that, list is not the structure you should be using if you want single instances of your object. There is a lot of overhead trying to search for equality in list as you will be searching the entire list. Try to use a set/dictionary based structure.
Your implementation of GetHasCode function is also not proper. It is based only on Name property while in equality you are using all the properties, this will lead to undesirable characteristics. Please read the MSDN documentation for a better implementation.
A simple Equals and GetHashCode is below:
protected bool Equals(Function other)
{
return string.Equals(Name, other.Name) && string.Equals(RT, other.RT) && ParamCount == other.ParamCount && Equals(ParamDT, other.ParamDT);
}
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((Function) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (Name != null ? Name.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (RT != null ? RT.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ ParamCount;
hashCode = (hashCode * 397) ^ (ParamDT != null ? ParamDT.GetHashCode() : 0);
return hashCode;
}
}
you can then use a HashSet which is a collection that contains no duplicate elements. This will ensure there is no code written for checking uniqueness in List. Link is here: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1?redirectedfrom=MSDN&view=netframework-4.7.2

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);
}
}

C# class definition HELP

This is a project question that i just cant seem to answer
using System;
namespace ConsoleApplication2
{
internal class Equipment : IComparable
{
private readonly string type;
private readonly int serialNo;
private string colour;
public decimal cost;
public Equipment(string type, int serialNo)
{
this.type = type == null ? "" : type.Trim();
this.serialNo = serialNo;
}
public string Key
{
get { return type + ":" + serialNo; }
}
int IComparable.CompareTo(object obj)
{
return 0;
}
}
}
(a) Override the appropriate method o ensure that different instances of the class that represent the same equipment item will be considered the same in the system.
(b) Override the appropriate method to enable instances of this class to be stored (and found) by key in a hash table
You should override the Equals and GetHashCode methods for this purpose.
Override Equals() with an appropriate logic of comparision
Override GetHashCode(), see GetHashCode Guidelines in C#
You must start reading this before doing such a task
Why is it important to override GetHashCode when Equals method is overriden in C#?
Writing GetHashCode manually is not that easy. Anyhow, that's code generated for this purpose by ReSharper. It's a complete solution. (It should be contained within your class definition of course). But what would you say, if you were asked - why and how it works? It might be embarassing.
So, apart from GetHashCode and Equals, which others have suggested you reading about, you might also look up http://msdn.microsoft.com/en-us/library/system.object.referenceequals.aspx as well as http://msdn.microsoft.com/en-us/library/a569z7k8(v=VS.100).aspx
As for the mystery behind 397 in GetHashCode, have a look at this question here on StackOverflow: Why is '397' used for ReSharper GetHashCode override?
public bool Equals(Equipment other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return Equals(other.colour, colour) && other.cost == cost && other.serialNo == serialNo && Equals(other.type, type);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != typeof (Equipment))
{
return false;
}
return Equals((Equipment) obj);
}
// note: if "Override the appropriate method to enable instances of this class
// to be stored (and found) by key in a hash table" is supposed to mean that only type and
// serialNo should be taken into account (since they are used to generate
// the Key value) - just remove the lines with cost and colour
public override int GetHashCode()
{
unchecked
{
int result = (colour != null ? colour.GetHashCode() : 0);
result = (result*397) ^ cost.GetHashCode();
result = (result*397) ^ serialNo;
result = (result*397) ^ (type != null ? type.GetHashCode() : 0);
return result;
}
}

overload Equals, is this wrong?

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.

Categories