1. 程式人生 > >C#中List集合操作IEqualityComparer正確使用方法

C#中List集合操作IEqualityComparer正確使用方法

基礎 類型 con sealed check reference tle list集合 union

C#中List集合操作IEqualityComparer正確使用方法

Except、Intersect、Union方法中的IEqualityComparer 怎麽使用

對於普通的string、及其他基礎類型並不需要實現,但是當你自己的引用類型實體需要進行比較就需要實現,特別是比較復雜的判等公示

IEqualityComparer 怎麽實現

需要實現bool Equals(CNMemo x, CNMemo y)int GetHashCode(CNMemo obj)方法,並繼承IEqualityComparer

resharper插件可以默認用alt-insert快捷鍵插入實現

我這裏有四個屬性要比較

MemoId:string

Content:string

Title:string

Tags:List

private sealed class CnMemoEqualityComparer : IEqualityComparer<CNMemo>
{
    public bool Equals(CNMemo x, CNMemo 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.MemoId, y.MemoId) && string.Equals(x.Content, y.Content) && string.Equals(x.Title, y.Title) && ((x.Tags == null && y.Tags == x.Tags) ||
    (x.Tags != null && y.Tags != null && x.Tags.Count == y.Tags.Count &&
     !x.Tags.Except(y.Tags).Any()));
    }

    public int GetHashCode(CNMemo obj)
    {
        return obj.ToString().GetHashCode();
    }
}
public static IEqualityComparer<CNMemo> CnMemoComparer { get; } = new CnMemoEqualityComparer();

註意: 這裏的方法中會先執行GetHashCode方法,如果GetHashCode方法返回的是不相同的值,那就直接忽略Equals方法,所以我在GetHashCode中沒有使用resharper的默認實現

public int GetHashCode(CNMemo obj)
{
    unchecked
    {
        var hashCode = (obj.MemoId != null ? obj.MemoId.GetHashCode() : 0);
        hashCode = (hashCode * 397) ^ (obj.Content != null ? obj.Content.GetHashCode() : 0);
        hashCode = (hashCode * 397) ^ (obj.Title != null ? obj.Title.GetHashCode() : 0);
        hashCode = (hashCode * 397) ^ (obj.Tags != null ? obj.Tags.GetHashCode() : 0);
        return hashCode;
    }
}

因為這樣Tags引用地址不一樣會導致GetHashCode不一致,obj.ToString().GetHashCode()如果tostring方法返回內容相同,那麽就會使用bool Equals(CNMemo x, CNMemo y)進行比較

如果之前實現了 IEquatable<CNMemo>也可使用x.Equals(y)來完成比較,這樣比較代碼就不用拷貝兩份了。

使用的時候就這樣new List<CNMemo>() { memo1 }.Except(new List<CNMemo>() { memo2 }, CNMemo.CnMemoComparer)

IEquatable

如果實現了 IEquatable<CNMemo>並且註意GetHashCode方法的實現註意上面的問題,也可直接使用new List<CNMemo>() { memo1 }.Except(new List<CNMemo>() { memo2 })

但是默認GetHashCode這樣實現有什麽負面效果待後續考證,目前沒有發現副作用

C#中List集合操作IEqualityComparer正確使用方法