y.MemoId) string.Equals(x.Content

时间:2021-09-08 03:38:28

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这样实现有什么负面效果待后续考证,目前没有发明副感化