IEqualityComparer和Linq Distinct - 硬代码GetHashCode()

时间:2014-07-16 13:45:17

标签: c# .net linq linq-to-objects

我有一组CustomObject和一个自定义IEqualityComparer<CustomObject>。我已经对IEqualityComparer.GetHashCode()方法进行了硬编码,以返回常量42

当我在数组上运行linq的Distinct方法时,没有任何过滤掉。谁知道为什么?

注意:我知道这里有很多关于这个问题的问题,但是,我看到过(C# Distinct on IEnumerable<T> with custom IEqualityComparerDistinct() with lambda?等)说确保实施GetHashCode。他们都没有解释,为什么它不起作用

代码:

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

测试:

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

这是我从运行测试中获得的输出:

 Expected: 5
 But was:  1

如果我调试测试,我可以看到GetHashCode正在被调用,那么为什么Distinct不会过滤掉所有'重复'?

1 个答案:

答案 0 :(得分:8)

  

当我在阵列上运行linq的Distinct方法时,没有任何过滤掉。谁知道为什么?

是 - Equals将为任何两个不同的对象返回false。在Equals实施中,您需要调用CustomObject.GetHashCode方法(不会被覆盖),您的自定义比较器{{1 }} 方法。如果您希望GetHashCode调用自定义Equals方法,则需要将其更改为:

GetHashCode

或者考虑到public bool Equals(CustomObject x, CustomObject y) { return GetHashCode(x) == GetHashCode(y); } 的实施,您可以将其简化为:

GetHashCode(CustomObject)

请注意,您public bool Equals(CustomObject x, CustomObject y) { return true; } 方法被<{1}}调用,但它正在调用您的GetHashCode方法来检查对象是否真的相同。 ..那时你说他们不是(除非是巧合)。