IEqualityComparer自定义比较器
仅当两个对象具有相同的GetHashCode()时才使用Equals()。
如果没有具有相同GetHashCode()的对象,则没有机会使用Equals()。
demo = demo.Distinct(EntityDto.ComparerByKey).ToList();
public class EntityDto
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public static IEqualityComparer<EntityDto> ComparerByKey { get; } = new EntityDtoEqualityComparer();
}
sealed class EntityDtoEqualityComparer : IEqualityComparer<EntityDto>
{
public int GetHashCode(EntityDto obj)
{
if (obj == null || obj.Property == null || obj.Property2 == null)
{
return 0;
}
return obj.Property.GetHashCode() ^ obj.Property2.GetHashCode();
}
public bool Equals(EntityDto x, EntityDto y)
{
if (ReferenceEquals(x, y))
{
return true;
}
if (ReferenceEquals(x, null))
{
return false;
}
if (ReferenceEquals(y, null))
{
return false;
}
if (x.GetType() != y.GetType())
{
return false;
}
return string.Equals(x.Property, y.Property) && string.Equals(x.Property2, y.Property2);
}
}
GetHashCode
用于在基于哈希的集合中插入和标识对象,方便检索。
引用类型自带的GetHashCode,基本上可以互相区别,但是效率不高。
值类型自带的GetHashCode基本上是不正确的。
如果重写了Equals方法,也要重新GetHashCode方法达到一致。
DynamicEqualityComparer
var test = testLis.Distinct(new DynamicEqualityComparer<DemoItem>(CustomEqualityFunc));
private bool CustomEqualityFunc(DemoItem feature1, DemoItem feature2)
{
float thread = 0.05f;
//公式:两个中心的距离 < thread ,认为是一个点
var min1 = 0;
var min2 = 0;
//if (x * x + y * y < thread * thread)
//{
// return true;
//}
if (Math.Abs(x) < thread)
{
return true;
}
if (Math.Abs(y) < thread)
{
return true;
}
return false;
}
/// <summary>
/// 动态创建相等比较器
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class DynamicEqualityComparer<T> : IEqualityComparer<T> where T : class
{
private readonly Func<T, T, bool> _predicate;
public DynamicEqualityComparer(Func<T, T, bool> func)
{
_predicate = func;
}
// 执行委托
public bool Equals(T x, T y) => _predicate(x, y);
// 默认 HashCode都相等,都执行 Equals
public int GetHashCode(T obj) => 0;
}