views:

34

answers:

2

I would like to use the Iesi.Collections HashedSet class for entity collections in NHibernate. The functionality I want is that duplicate entities cannot be added. I would like entities to be considered duplicate if they share the Id (i.e. primary key) field, or, if they have Id == 0 (i.e. unsaved), then certain key properties are compared instead.

I notice that by default the HashedSet appears to define duplicates using reference equality. What do I need to change in order to get the HashedSet to define duplication according to the rules I described above? (E.g. override .Equals, override ==, etc).

A: 

You need to override GetHashCode method.

Sly
Thanks for your suggestion. I overrode GetHashCode as return Id.GetHashCode(), but it doesn't work. The HashedSet can contain two entities with the Id.
David
..with the SAME Id I mean.
David
HashedSet won't contain two objects with the hashcode. You should check implementation I think
Sly
[TestFixture] public class EntityTestSuite { [Test] public void Two_Entities_With_The_Same_Id_Have_The_Same_Hashcode() { Entity bob = new Entity() { Id = 1, Name = "Bob" }; Entity margaret = new Entity() { Id = 1, Name = "Margaret" }; Assert.That(bob.GetHashCode() == margaret.GetHashCode()); }...
David
...continued...
David
[Test] public void Two_Entities_With_The_Same_Id_Cannot_Be_Inserted_Into_A_Set() { ISet<Entity> entities = new HashedSet<Entity>(); Entity bob = new Entity() { Id = 1, Name = "Bob" }; Entity margaret = new Entity() { Id = 1, Name = "Margaret" }; entities.Add(bob); entities.Add(margaret); Assert.That(entities.Count == 1); } }
David
public class Entity { public int Id { get; set; } public string Name { get; set; } public override int GetHashCode() { return Id.GetHashCode(); } }
David
The first comment contains the first half of an NUnit test fixture class, the second comment contains the second haff. The third comment contains a simple class called Entity.
David
If you run this code, you'll see the first test, which tests whether the two instances have the same hash code, passes, whereas the second test, which tests whether the size of the hashed set is still 1 after both instances are added in, returns false (i.e. both insances have been added to the hashed set).
David
+1  A: 

Equals and GetHashCode must always be overridden together. The documentation for GetHashCode states:

Derived classes that override GetHashCode must also override Equals to guarantee that two objects considered equal have the same hash code; otherwise, the Hashtable type might not work correctly.

Jon Skeet's answer to this question provides additional information.

Overriding the equality operators is optional but I recommend it.

Jamie Ide