Reputation: 12295
I have an array of CustomObject
s and a custom IEqualityComparer<CustomObject>
. I have hard coded the IEqualityComparer.GetHashCode()
method to return a constant 42
.
When I run linq's Distinct
method on the array, nothing is filtered out. Anyone know why?
Note: I know there are a number of questions on here about this issue, however, the ones I've seen (C# Distinct on IEnumerable<T> with custom IEqualityComparer, Distinct() with lambda?, etc) only say to make sure to implement GetHashCode
. None of them explain, why it doesn't work.
Code:
public class CustomObject
{
public string Name { get; set; }
}
public class CustomObjectEqualityComparer : IEqualityComparer<CustomObject>
{
public bool Equals(CustomObject x, CustomObject y)
{
//Every CustomObject should now be 'equal'!
return x.GetHashCode() == y.GetHashCode();
}
public int GetHashCode(CustomObject obj)
{
//Every CustomObject should now be 'equal'!
return 42;
}
}
Test:
[TestFixture]
public class TestRunner
{
private CustomObject[] customObjects =
{
new CustomObject {Name = "Please"},
new CustomObject {Name = "Help"},
new CustomObject {Name = "Me"},
new CustomObject {Name = "Stack"},
new CustomObject {Name = "Overflow"},
};
[Test]
public void DistinctTest()
{
var distinctArray =
customObjects.Distinct(new CustomObjectEqualityComparer()).ToArray();
//Since every CustomObject is 'Equal' there should only be
//1 element in the array.
Assert.AreEqual(1, distinctArray.Length);
}
}
This is the output I get from running the test:
Expected: 5
But was: 1
If I debug the test, I can see that GetHashCode
is being called, so why isn't Distinct
filtering out all the 'duplicates'?
Upvotes: 3
Views: 2952
Reputation: 1500805
When I run linq's Distinct method on the array, nothing is filtered out. Anyone know why?
Yes - Equals
is going to return false
for any two distinct objects. Within your Equals
implementation, you're calling the CustomObject.GetHashCode
method (which isn't overridden), not your custom comparer's GetHashCode
method. If you expected Equals
to call your custom GetHashCode
method, you'd need to change it to:
public bool Equals(CustomObject x, CustomObject y)
{
return GetHashCode(x) == GetHashCode(y);
}
Or given the implementation of GetHashCode(CustomObject)
, you can just simplify it to:
public bool Equals(CustomObject x, CustomObject y)
{
return true;
}
Note that your GetHashCode
method was being called by Distinct()
, but it was then calling your Equals
method to check that the objects were really equal... and at that point you were saying that they weren't (barring a massive coincidence).
Upvotes: 8