前言
C# LINQ提供很多方便的List<T>查詢方法,如果需要查詢列表中沒有重複的項目時會呼叫Distinct(),這時.NET會使用預設的比較器去做查詢,也就是用物件的HashCode做比較。
假設T是int,可以預期結果是1, 2, 3, 4
List<int> numList = new List() { 1, 2, 2, 3, 4 }
var listDistinct = numList.Distinct();
//OUTPUT: 1, 2, 3, 4
當如果T是一個物件(object)呢?
class MyObj
{
public int Num { get; set; } = 0;
public string Text { get; set; } = string.Empty;
}
實作IEqualityComparer
只需要實作IEqualityComparer<T>就可以自訂比較的規則,如果只要比較Text屬性,那就把Num拿掉即可。
class MyObjEqualityComparer : IEqualityComparer<MyObj>
{
public bool Equals(MyObj obj1, MyObj obj2)
{
if (ReferenceEquals(obj1, obj2))
return true;
if (obj1 is null || obj2 is null)
return false;
return obj1.Num == obj2.Num
&& obj1.Text == obj2.Text;
}
public int GetHashCode(MyObj obj) => obj.Num ^ obj.Text.GetHashCode();
}
使用時,只需要將Comparer傳給Distinct即可。超級方便。
IEnumerable<MyObj> noduplicates =
myObjList.Distinct(new MyObjEqualityComparer());
結語
在此之前,自己都先Select要比較的項目,Distinct之後再去一個一個Find或是First,但用多了實在很麻煩,而且維護上邏輯切換更是一大問題。
好在C#.NET有提供IEqualityComparer<T>,只要按規則走就能非常上手,現在只要抽換Comparer就能做到邏輯切換的功能。
發佈留言