为什么我的动态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 不起作用?
因为您的相等比较器无法正确实现GetHashCode
。GetHashCode
实现必须为比较相等的元素生成相同的代码。此处不会发生这种情况,因为相等比较是自定义的,而哈希代码不会相应地生成。
要完成这项工作,您需要执行以下两项操作之一:
-
使比较器接受哈希代码实现作为附加参数,即
x => x.ID.GetHashCode()
并转发到这一点。这是最简单的,也是您在实践中应该做的。 -
修改
GetHashCode
,使其是参与比较的属性的哈希代码的聚合函数(这里是ID
属性) - 单个哈希代码的直接异或将起作用(即使它可能不是最佳的)。这给您留下了如何检测哪个的问题比较属性。为了能够自动回答该问题,您需要接受表达式树而不是用于比较的委托,即
Expression<Func<T, T, bool>>
,然后访问表达式树以确定要做什么。这注定不是一件容易的事。