C#在Distinct()中使用IEqualityComparer<T>
基本语法varuniqueItemssourceCollection.Distinct(newYourCustomComparer());其中YourCustomComparer()是你实现的IEqualityComparerT类的实例。完整示例沿用之前定义的Person类和PersonNameComparerusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;publicclassPerson{publicstringName{get;set;}publicintAge{get;set;}publicoverridestringToString(){return$Person(Name{Name}, Age{Age});}}// 根据 Name忽略大小写判断是否相等publicclassPersonNameComparer:IEqualityComparerPerson{publicboolEquals(Personx,Persony){if(xnullynull)returntrue;if(xnull||ynull)returnfalse;returnstring.Equals(x.Name,y.Name,StringComparison.OrdinalIgnoreCase);}publicintGetHashCode(Personobj){if(objnull)return0;returnobj.Name?.GetHashCode(StringComparison.OrdinalIgnoreCase)??0;}}使用Distinct(IEqualityComparerT)classProgram{staticvoidMain(){// 创建一个包含“重复”姓名但大小写不同的列表varpeoplenewListPerson{newPerson{NameAlice,Age30},newPerson{Namealice,Age25},// 名字相同大小写不同newPerson{NameBob,Age35},newPerson{NameBOB,Age40},// 名字相同大小写不同newPerson{NameCharlie,Age28}};Console.WriteLine(原始列表:);foreach(varpersoninpeople){Console.WriteLine(person);}// 使用自定义比较器进行去重vardistinctPeoplepeople.Distinct(newPersonNameComparer());Console.WriteLine(\n去重后根据名字忽略大小写:);foreach(varpersonindistinctPeople){Console.WriteLine(person);}}}输出结果原始列表: Person(NameAlice, Age30) Person(Namealice, Age25) Person(NameBob, Age35) Person(NameBOB, Age40) Person(NameCharlie, Age28) 去重后根据名字忽略大小写: Person(NameAlice, Age30) Person(NameBob, Age35) Person(NameCharlie, Age28)关键点说明选择第一个Distinct()在遇到“相等”的元素时通常会保留第一次出现的那个元素。在上面的例子中“Alice” 被保留而后面的 “alice” 被去除了。必须提供比较器如果你的对象没有合适的Equals和GetHashCode重写或者你需要不同于默认行为的比较逻辑如忽略大小写、比较特定属性等就必须传入一个IEqualityComparerT实例。否则Distinct()会使用引用相等性对于引用类型或值相等性对于值类型这可能不是你想要的结果。链式调用Distinct()返回的是一个IEnumerableT所以你可以继续进行其他 LINQ 操作varresultpeople.Distinct(newPersonNameComparer()).Where(pp.Age30).OrderBy(pp.Name);更简洁的写法如果比较逻辑简单如果只是简单的字符串忽略大小写去重可以直接用内置的StringComparervarnamesnewListstring{Alice,alice,Bob,BOB};vardistinctNamesnames.Distinct(StringComparer.OrdinalIgnoreCase);但对于复杂对象自定义IEqualityComparerT是最清晰和可复用的方式。总之在Distinct()中使用IEqualityComparerT就是将其实例作为参数传递给Distinct()方法从而精确控制“什么是重复”的定义。