使用具有公差的 IEqualityComparer GetHashCode

Using IEqualityComparer GetHashCode with a tolerance

我正在尝试实现一个 IEqualityComparer 对日期比较有容差。我也调查了 this question。问题是我无法使用解决方法,因为我在 LINQ .GroupJoin() 中使用 IEqualityComparer。我已经尝试了一些允许容忍的实现。我可以让 Equals() 工作,因为我有两个对象,但我不知道如何实现 GetHashCode().

我最好的尝试是这样的:

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

使用 .GroupJoin()GetHashCode() 构建一个 HashTable 它应用天数添加到 both/all 对象。这行不通。

我看不出有什么方法可以根据您给定的条件生成逻辑哈希码。
哈希码用于确定 2 个日期是否应该粘在一起。如果他们应该组合在一起,那么他们必须 return 相同的哈希码。

如果您的 "float" 是 5 天,这意味着 1/1/2000 必须生成与 1/4/2000 相同的哈希码,而 1/4/2000 必须生成与 1 相同的哈希码/8/2000(因为它们相距不到 5 天)。这意味着 1/1/2000 与 1/8/2000 具有相同的代码(因为如果 a=b 且 b=c,则 a=c)。

1/1/2000 和 1/8/2000 在 5 天之外 "float"。

这个问题从概念上来说是不可能的。您正在尝试以一种不具有您尝试对其执行的操作所必需的相等形式的方式来比较对象。例如,GroupJoin 取决于以下假设:如果 A 等于 B,并且 B 等于 C,则 A 等于 C,但在您的情况下,事实并非如此。 A 和 B 可能 "close enough" 在一起,您想要将它们分组,但 A 和 C 可能不在一起。

您根本不需要实施 IEqualityComparer,因为您无法履行它所要求的合同。如果你想创建一个集合中的项目到另一个集合中所有项目的映射 "close enough" 那么你将需要自己编写该算法(有效地这样做可能很难,但这样做效率低下不应该那么困难),而不是使用 GroupJoin,因为它无法执行该操作。