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;
}
posted @ 2019-12-31 18:14  wesson2019  阅读(302)  评论(0编辑  收藏  举报