为什么我的动态IEqualityComparer不起作用

本文关键字:不起作用 IEqualityComparer 动态 我的 为什么 | 更新日期: 2024-10-25 14:16:08

我有一个类

public class Foo
{
  public int ID { get; set; }
}

我已经实现了一个LinqEqualityComparer,以允许对Except extenion方法进行动态IEqualityComparer测试。

public class LinqEqualityComparer<T> : IEqualityComparer<T>
{
    protected Func<T, T, bool> Comparison { get; set; }
    public LinqEqualityComparer(Func<T, T, bool> comparison)
    {
        Comparison = comparison;
    }
    public bool Equals(T x, T y)
    {
        return Comparison(x, y);
    }

    public int GetHashCode(T obj)
    {
        return obj.GetHashCode();
    }
}

我创建了以下代码来测试它:

IEnumerable<Foo> settings = new Foo[]
{
  new Foo{ID = 1},
  new Foo{ID = 2}
};
IEnumerable<Foo> currentSettings = new Foo[]
{
  new Foo{ID = 1},
  new Foo{ID = 2},
  new Foo{ID = 3}
};
IEqualityComparer<Foo> comparer = new LinqEqualityComparer<Foo>((x, y) => x.ID == y.ID);
IEnumerable<Foo> missing = currentSettings.Except(settings, comparer);

然而,Foos 1,2和3都存在于"缺失"变量中。

为什么这个 LinqEqualityComparer 不起作用?

为什么我的动态IEqualityComparer不起作用

因为您的相等比较器无法正确实现GetHashCodeGetHashCode实现必须为比较相等的元素生成相同的代码。此处不会发生这种情况,因为相等比较是自定义的,而哈希代码不会相应地生成。

要完成这项工作,您需要执行以下两项操作之一:

  1. 使比较器接受哈希代码实现作为附加参数,即 x => x.ID.GetHashCode()并转发到这一点。这是最简单的,也是您在实践中应该做的。

  2. 修改GetHashCode,使其是参与比较的属性的哈希代码的聚合函数(这里是ID属性) - 单个哈希代码的直接异或将起作用(即使它可能不是最佳的)。

    这给您留下了如何检测哪个的问题比较属性。为了能够自动回答该问题,您需要接受表达式树而不是用于比较的委托,即Expression<Func<T, T, bool>>,然后访问表达式树以确定要做什么。这注定不是一件容易的事。