首页 > 解决方案 > 在 lambda 上执行 distinct() 时替换 IEquatable 接口

问题描述

我有这个实现IEquatable<T>接口的类

public class ArticleDescriptionDetails : IEquatable<ArticleDescriptionDetails>
{
    public string Code { get; set; }
    public string Value { get; set; }
    public bool Hidden { get; set; }

    public bool Equals(ArticleDescriptionDetails other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Code == other.Code;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        return obj.GetType() == GetType() && Equals((ArticleDescriptionDetails) obj);
    }

    public override int GetHashCode() => ((Code != null ? Code.GetHashCode() : 0) * 397) ^ Hidden.GetHashCode();

    public static bool operator ==(ArticleDescriptionDetails left, ArticleDescriptionDetails right) => Equals(left, right);

    public static bool operator !=(ArticleDescriptionDetails left, ArticleDescriptionDetails right) => !Equals(left, right);
}

我需要这个,因为我想以IEquatable<ArticleDescriptionDetails>这种方式返回一个:

return result.OrderBy(x => x.Code).ThenBy(y => y.Hidden).Distinct();

有没有办法在不使用IEquatable<T>界面的情况下做同样的事情?

标签: c#.net

解决方案


您可以使用 DistinctBy 方法并执行

return result.OrderBy(x => x.Code).ThenBy(y => y.Hidden).DistinctBy(z => z.Code); 

但是 linq 中不存在 DistinctBy 方法,但您可以在 morelinq 包中找到它https://www.nuget.org/packages/MoreLinq.Source.MoreEnumerable.DistinctBy/

但是编写自己的方法版本也很容易:首先需要定义一个 IEqualityComparer


    public class KeyEqualityComparer<T, K> : IEqualityComparer<T>
    {
        private readonly Func<T, K> selector;

        public KeyEqualityComparer(Func<T, K> keySelector)
        {
            selector = keySelector;
        }

        public bool Equals(T x, T y)
        {
            return selector(x).Equals(selector(y));
        }

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

您可以在 Distinct 方法中使用此 IEqualityComparer :

        public static IEnumerable<T> DistinctBy<T, K>(this IEnumerable<T> list, Func<T, K> keySelector)
        {
            var equalityComparer = new KeyEqualityComparer<T, K>(keySelector);
            return list.Distinct(equalityComparer);
        }

推荐阅读