简体   繁体   English

使用具有公差的IEqualityComparer GetHashCode

[英]Using IEqualityComparer GetHashCode with a tolerance

I am trying to implement an IEqualityComparer that has a tolerance on a date comparison. 我正在尝试实现对日期比较有容忍的IEqualityComparer I have also looked into this question . 我也调查了这个问题 The problem is that I can't use a workaround because I am using the IEqualityComparer in a LINQ .GroupJoin() . 问题是我无法使用替代方法,因为我在LINQ .GroupJoin()使用IEqualityComparer I have tried a few implementations that allow for tolerance. 我尝试了一些允许容忍的实现。 I can get the Equals() to work because I have both objects but I can't figure out how to implement GetHashCode() . 我可以使Equals()正常工作,因为我有两个对象,但是我不知道如何实现GetHashCode()

My best attempt looks something like this: 我最大的尝试是这样的:

public class ThingWithDateComparer : IEqualityComparer<IThingWithDate>
{
    private readonly int _daysToAdd;

    public ThingWithDateComparer(int daysToAdd)
    {
        _daysToAdd = daysToAdd;
    }

    public int GetHashCode(IThingWithDate obj)
    {
        unchecked
        {
            var hash = 17;
            hash = hash * 23 + obj.BirthDate.AddDays(_daysToAdd).GetHashCode();
            return hash;
        }
    }

    public bool Equals(IThingWithDate x, IThingWithDate y)
    {
        throw new NotImplementedException();
    }
}

public interface IThingWithDate
{
    DateTime BirthDate { get; set; }
}

With .GroupJoin() building a HashTable out of the GetHashCode() it applies the days to add to both/all objects. 使用.GroupJoin()GetHashCode() .GroupJoin()构建HashTable时,它将应用添加到两个/所有对象的天数。 This doesn't work. 这行不通。

The problem is impossible, conceptually. 从概念上讲,这个问题是不可能的。 You're trying to compare objects in a way that doesn't have a form of equality that is necessary for the operations you're trying to perform with it. 您正在尝试以一种没有相等形式的方式来比较对象,而相等形式是您尝试执行该操作所必需的。 For example, GroupJoin is dependant on the assumption that if A is equal to B, and B is equal to C, then A is equal to C, but in your situation, that's not true. 例如, GroupJoin取决于以下假设:如果A等于B,并且B等于C,那么A等于C,但是在您的情况下,这是不正确的。 A and B may be "close enough" together for you to want to group them, but A and C may not be. A和B可能“足够接近”在一起,以便您希望将它们分组,但A和C可能不是。

You're going to need to not implement IEqualityComparer at all, because you cannot fulfill the contract that it requires. 您将根本不需要实现IEqualityComparer ,因为您无法履行它所需的合同。 If you want to create a mapping of items in one collection to all of the items in another collection that are "close enough" to it then you're going to need to write that algorithm yourself (doing so efficiently is likely to be hard, but doing so inefficiently isn't shouldn't' be that difficult), rather than using GroupJoin , because it's not capable of performing that operation. 如果您要创建一个集合中的项目到另一个集合中所有“足够接近”的项目的映射,则您需要自己编写该算法(如此高效地执行可能很困难,但这样做效率不低不是那么困难),而不是使用GroupJoin ,因为它无法执行该操作。

I can't see any way to generate a logical hash code for your given criteria. 我看不到任何方法来为您的给定条件生成逻辑哈希码。
The hash code is used to determine if 2 dates should stick together. 哈希码用于确定2个日期是否应该在一起。 If they should group together, than they must return the same hash code. 如果它们应该组合在一起,则必须返回相同的哈希码。

If your "float" is 5 days, that means that 1/1/2000 must generate the same hash code as 1/4/2000, and 1/4/2000 must generate the same hashcode as 1/8/2000 (since they are both within 5 days of each other). 如果您的“浮动时间”为5天,则意味着1/1/2000必须生成与1/4/2000相同的哈希码,而1/4/2000必须生成与1/8/2000相同的哈希码(因为它们都在5天内。 That implies that 1/1/2000 has the same code as 1/8/2000 (since if a=b and b=c, a=c). 这意味着1/1/2000具有与1/8/2000相同的代码(因为如果a = b和b = c,则a = c)。

1/1/2000 and 1/8/2000 are outside the 5 day "float". 1/1/2000和1/8/2000不在5天“浮动”期间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM