There is a passage from NHibernate documentation:
Note: if you define an ISet of composite elements, it is very important to implement Equals() and GetHashCode() correctly.
What does correctly mean there? Is it neccessary to implement those methods for all value objects in domain?
EXTENDING MY QUESTION
In the article Marc attached user Albic states:
It's actually very hard to implement GetHashCode() correctly because, in addition to the rules Marc already mentioned, the hash code should not change during the lifetime of an object. Therefore the fields which are used to calculate the hash code must be immutable.
I finally found a solution to this problem when I was working with NHibernate. My approach is to calculate the hash code from the ID of the object. The ID can only be set though the constructor so if you want to change the ID, which is very unlikely, you have to create a new object which has a new ID and therefore a new hash code. This approach works best with GUIDs because you can provide a parameterless constructor which randomly generates an ID.
I suddenly realized what I've got inside my AbstractEntity class:
public abstract class AbstractEntity<T> where T : AbstractEntity<T> {
private Nullable<Int32> hashCode;
public virtual Guid Id { get; protected set; }
public virtual Byte[] Version { get; set; }
public override Boolean Equals(Object obj) {
var other = obj as T;
if(other == null) {
return false;
}
var thisIsNew = Equals(this.Id, Guid.Empty);
var otherIsNew = Equals(other.Id, Guid.Empty);
if(thisIsNew && otherIsNew) {
return ReferenceEquals(this, other);
}
return this.Id.Equals(other.Id);
} // public override Boolean Equals(Object obj) {
public override Int32 GetHashCode() {
if(this.hashCode.HasValue) {
return this.hashCode.Value;
}
var thisIsNew = Equals(this.Id, Guid.Empty);
if(thisIsNew) {
this.hashCode = base.GetHashCode();
return this.hashCode.Value;
}
return this.Id.GetHashCode();
} // public override Int32 GetHashCode() {
public static Boolean operator ==(AbstractEntity<T> l, AbstractEntity<T> r) {
return Equals(l, r);
}
public static Boolean operator !=(AbstractEntity<T> l, AbstractEntity<T> r) {
return !Equals(l, r);
}
} // public abstract class AbstractEntity<T>...
As all components are nested within entities should I then implement Equals() and GetHashCode() for them?
Correctly means that GetHashCode returns the same hash code for the entities that are expected to be equal. Because equality of 2 entities is made by comparison of that code.
On the other side, that means that for entities that are not equal, the uniqueness of hash code has to be guaranteed, as much as it possible.
The documentation for Equals and GetHashCode explain this well and include specific guidance on implementation for value objects. For value objects, Equals is true if the objects are the same type and the public and private fields are equal. However, this explanation applies to framework value types and you are free to create your own Equals by overriding it.
GetHashCode has two rules that must be followed:
If two objects compare as equal, the GetHashCode method for each object must return the same value. However, if two objects do not
compare as equal, the GetHashCode methods for the two object do not
have to return different values.
The GetHashCode method for an object must consistently return the same hash code as long as there is no modification to the object state
that determines the return value of the object's Equals method. Note
that this is true only for the current execution of an application,
and that a different hash code can be returned if the application is
run again.
Related
I am trying to implement an immutable Point class where two Point instances are considered equal if they have the same Coordinates. I am using Jon Skeet's implementation of a Coordinate value type.
For comparing equality of Points I have also inherited EqualityComparer<Point> and IEquatable<Point> and I have a unit test as below:
Point.cs:
public class Point : EqualityCompararer<Point>, IEquatable<Point>
{
public Coordinate Coordinate { get; private set; }
// EqualityCompararer<Point>, IEquatable<Point> methods and other methods
}
PointTests.cs:
[Fact]
public void PointReferencesToSamePortalAreNotEqual()
{
var point1 = new Point(22.0, 24.0);
var point2 = new Point(22.0, 24.0);
// Value equality should return true
Assert.Equal(point1, point2);
// Reference equality should return false
Assert.False(point1 == point2);
}
Now I am really confused by the 3 interface/abstract methods that I must implement. These are:
IEquatable<Point>.Equals(Point other)
EqualityComparer<Point>.Equals(Point x, Point y)
EqualityComparer<Point>.GetHashCode(Point obj)
And since I have overriden IEquatable<Point>.Equals, according to MSDN I must also implement:
Object.Equals(object obj)
Object.GetHashCode(object obj)
Now I am really confused about all the Equals and GetHashCode methods that are required to satisfy my unit test (Reference equality should return false and value equality should return true for point1 and point2).
Can anyone explain a bit further about Equals and GetHashCode?
Because Coordinate already implments GetHashCode() and Equals(Coordinate) for you it is actually quite easy, just use the underlying implmentation
public class Point : IEquatable<Point>
{
public Coordinate Coordinate { get; private set; }
public override int GetHashCode()
{
return Coordinate.GetHashCode();
}
public override bool Equals(object obj)
{
return this.Equals(obj as Point);
}
public bool Equals(Point point)
{
if(point == null)
return false;
return this.Coordinate.Equals(point.Coordinate);
}
}
the IEquatable<Point> is unnecessary as all it does is save you a extra cast. It is mainly for struct type classes to prevent the boxing of the struct in to the object passed in to bool Equals(object).
Equals:
Used to check if two objects are equal. There are several checks for equality (by value, by reference), and you really want to have a look at the link to see how they work, and the pitfalls when you don't know who is overriding them how.
GetHashCode:
A hash code is a numeric value that is used to insert and identify an object in a hash-based collection such as the Dictionary class, the Hashtable class, or a type derived from the DictionaryBase class. The GetHashCode method provides this hash code for algorithms that need quick checks of object equality.
Let's assume you're having two huge objects with heaps of objects inside, and that comparing them might take a very long time. And then you have a collection of those objects, and you need to compare them all. As the definitions say, GetHashCode will return a simple number you can compare if you don't want to compare the two objects. (and assuming you implemented them correctly, two different objects will not have the same hashcode, while objects who are supposed to be "equal" will).
And if you want Jon Skeet's opinion on something similar, look here.
This question already has answers here:
Why is it important to override GetHashCode when Equals method is overridden?
(15 answers)
Closed 9 years ago.
I am using Entity Framework 5. In my C# code I want to compare if two objects are equal. If there are not then I want to issue an update.
I have been told I need to override the .Equals method and then also the gethascode method. My classes look like this:
public class Students {
public int PersonId { get; set; }
public string Name { get; set; }
public int Age {get; set;}
}
Can some explain why I need to override .Equals and .GetHashCode. Also can someone give me an example. In particular I am not sure about the hashcode. Note that my PersonId is a unique number for this class.
You need to override the two methods for any number of reasons. The GetHashCode is used for insertion and lookup in Dictionary and HashTable, for example. The Equals method is used for any equality tests on the objects. For example:
public partial class myClass
{
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
For GetHashCode, I would have done:
public int GetHashCode()
{
return PersonId.GetHashCode() ^
Name.GetHashCode() ^
Age.GetHashCode();
}
If you override the GetHashCode method, you should also override Equals, and vice versa. If your overridden Equals method returns true when two objects are tested for equality, your overridden GetHashCode method must return the same value for the two objects.
Classes are reference types. When you create two objects and store them in variables you're only storing the reference to them. This means if you attempt to compare them you will only be comparing two references which will only be equal if they're pointing to the same object on heap. If you want to change that behavior you will have to override Equals.
Also some collections depend on GetHashCode to store elements in tree-like(or any other) structures that need some means of comparison between two objects of a given class. Which is why you need to implement these methods if you need your defined class to behave correctly under the specified circumstances.
A typical implementation of GetHashCode would be the xor of class's fields which is given in #No Idea For Name's answer. But since PersonId is unique in your example, you could also use that:
public int GetHashCode()
{
return PersonId.GetHashCode();
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is it important to override GetHashCode when Equals method is overriden in C#?
I was looking into the following class in my Object Model and could not understand the significance of adding GetHashCode() in the Class.
Sample Class
public class SampleClass
{
public int ID { get; set; }
public String Name { get; set; }
public String SSN_Number { get; set; }
public override bool Equals(Object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
SampleClass cls = (SampleClass)obj;
return (ID == cls.ID) &&
(Name == cls.Name) &&
(SSN_Number == cls.SSN_Number);
}
public override int GetHashCode()
{
return ID.GetHashCode() ^ Name.GetHashCode() ^ SSN_Number.GetHashCode();
}
}
Suppose I have a list of Sample Class Object and I want to get a specific index. Then Equals() can help me to get that record. Why should I use GetHashCode() ?
You need to handle both, because GetHashCode() is used by many collection implementations (like Dictionary) in concert with the Equals method. The important thing is that if you override the implementation of Equals, then you must override GetHashCode in such a way that any two objects that are Equal according to your new implementation also must return an identical Hash Code.
If they don't, then they will not work in Dictionary's properly. It's generally not that hard. One way that I often times do this is by taking the Properties of an object that I use for equality, and joining them together in a String object, and then return String.GetHashCode.
String has a pretty good implementation of GetHashCode that returns a wide range of integers for various values that make for good spreads in a sparse collection.
It is necessary to provide an override to GetHashCode, when your custom class overrides Equals. If you omit GetHashCode, you will get a compiler warning saying "A public type overrides System.Object.Equals but does not override System.Object.GetHashCode".
GetHashCode returns a value based on the current instance that is suited for hashing algorithms and data structures such as a hash table. Two objects that are the same type and are equal must return the same hash code to ensure that instances of System.Collections.HashTable and System.Collections.Generic.Dictionary<TKey, TValue> work correctly.
Suppose it was not necessary to override the GetHashCode in your custom class, the hash based collections would have to then use the base class' Object.GetHashCode which might not give correct results for all instances of your custom class.
If you observe the code you have posted, your Equals method compares
ID, Name and SSN for the 2 instances to return equality result
and the same attributes are being used for the hashing algorithm
(ID^Name^SSN) inside your GetHashCode method.
I have a class it contains some string members, some double members and some array objects.
I create two objects of this class, is there any simplest, efficient way of comparing these objects and say their equal? Any suggestions?
I know how to write a compare function, but will it be time consuming.
The only way you can really do this is to override bool Object.Equals(object other) to return true when your conditions for equality are met, and return false otherwise. You must also override int Object.GetHashCode() to return an int computed from all of the data that you consider when overriding Equals().
As an aside, note that the contract for GetHashCode() specifies that the return value must be equal for two objects when Equals() would return true when comparing them. This means that return 0; is a valid implementation of GetHashCode() but it will cause inefficiencies when objects of your class are used as dictionary keys, or stored in a HashSet<T>.
The way I implement equality is like this:
public class Foo : IEquatable<Foo>
{
public bool Equals(Foo other)
{
if (other == null)
return false;
if (other == this)
return true; // Same object reference.
// Compare this to other and return true/false as appropriate.
}
public override bool Equals(Object other)
{
return Equals(other as Foo);
}
public override int GetHashCode()
{
// Compute and return hash code.
}
}
A simple way of implementing GetHashCode() is to XOR together the hash codes of all of the data you consider for equality in Equals(). So if, for example, the properties you compare for equality are string FirstName; string LastName; int Id;, your implementation might look like:
public override int GetHashCode()
{
return (FirstName != null ? FirstName.GetHashCode() : 0) ^
(LastName != null ? LastName.GetHashCode() : 0) ^
Id; // Primitives of <= 4 bytes are their own hash codes
}
I typically do not override the equality operators, as most of the time I'm concerned with equality only for the purposes of dictionary keys or collections. I would only consider overriding the equality operators if you are likely to do more comparisons by value than by reference, as it is syntactically less verbose. However, you have to remember to change all places where you use == or != on your object (including in your implementation of Equals()!) to use Object.ReferenceEquals(), or to cast both operands to object. This nasty gotcha (which can cause infinite recursion in your equality test if you are not careful) is one of the primary reasons I rarely override these operators.
The 'proper' way to do it in .NET is to implement the IEquatable interface for your class:
public class SomeClass : IEquatable<SomeClass>
{
public string Name { get; set; }
public double Value { get; set; }
public int[] NumberList { get; set; }
public bool Equals(SomeClass other)
{
// whatever your custom equality logic is
return other.Name == Name &&
other.Value == Value &&
other.NumberList == NumberList;
}
}
However, if you really want to do it right, this isn't all you should do. You should also override the Equals(object, object) and GetHashCode(object) methods so that, no matter how your calling code is comparing equality (perhaps in a Dictionary or perhaps in some loosely-typed collection), your code and not reference-type equality will be the determining factor:
public class SomeClass : IEquatable<SomeClass>
{
public string Name { get; set; }
public double Value { get; set; }
public int[] NumberList { get; set; }
/// <summary>
/// Explicitly implemented IEquatable method.
/// </summary>
public bool IEquatable<SomeClass>.Equals(SomeClass other)
{
return other.Name == Name &&
other.Value == Value &&
other.NumberList == NumberList;
}
public override bool Equals(object obj)
{
var other = obj as SomeClass;
if (other == null)
return false;
return ((IEquatable<SomeClass>)(this)).Equals(other);
}
public override int GetHashCode()
{
// Determine some consistent way of generating a hash code, such as...
return Name.GetHashCode() ^ Value.GetHashCode() ^ NumberList.GetHashCode();
}
}
Just spent the whole day writing an extension method looping through reflecting over properties of an object with various complex bits of logic to deal with different property type and actually got it close to good, then at 16:55 it dawned on me that if you serialize the two object, you simply need compare the two strings ... duh
So here is a simple serializer extension method that even works on Dictionaries
public static class TExtensions
{
public static string Serialize<T>(this T thisT)
{
var serializer = new DataContractSerializer(thisT.GetType());
using (var writer = new StringWriter())
using (var stm = new XmlTextWriter(writer))
{
serializer.WriteObject(stm, thisT);
return writer.ToString();
}
}
}
Now your test can be as simple as
Asset.AreEqual(objA.Serialise(), objB.Serialise())
Haven't done extensive testing yet, but looks promising and more importantly, simple. Either way still a useful method to have in your utility set right ?
The best answer is to implement IEquatable for your class - it may not be the answer you want to hear, but that's the best way to implement value equivalence in .NET.
Another option would be computing a unique hash of all of the members of your class and then doing value comparisons against those, but that's even more work than writing a comparison function ;)
Since these are objects my guess is that you will have to override the Equals method for objects. Otherwise the Equals method will give you ok only if both objects refering to the same object.
I know this is not the answer you want. But since there is little number of properties in your class you can easily override the method.
a class has an ID property and this property gets value from a primary key column of an SQL table.
Is it a good practice if I write
public override int GetHashCode()
{
return this.ID + GetType().GetHashCode();
}
into my class? (Equals overrided already on the same way.)
Why would you particularly want to include the type in the hashcode? I can see how that could be useful if you had a lot of different types of object with the same ID in the same map, but normally I'd just use
public override int GetHashCode()
{
return ID; // If ID is an int
// return ID.GetHashCode(); // otherwise
}
Note that ideas of equality become tricky within inheritance hierarchies - another reason to prefer composition over inheritance. Do you actually need to worry about this? If you can seal your class, it will make the equality test easier as you only need to write:
public override bool Equals(object obj)
{
MyType other = obj as other;
return other != null && other.ID == ID;
}
(You may well want to have a strongly-typed Equals method and implement IEquatable.)
Why can't you just do
public override int GetHashCode() {
return this.ID.GetHashCode();
}
I am not sure if what you are doing is good practice because I am not familiar with how the hash code is assigned to a type instance. And the purpose of the hashcode is to have a consistence representation of the object in Int32 form.