Equals和GetHashCode
Equals每個實作都必須遵循以下約定:
- 自反性(Reflexive): x.equals(x)必須回傳true.
- 對稱性(Symmetric): x.equals(y)為true時,y.equals(x)也為true.
- 傳遞性(Transitive): 對于任何非null的應用值x,y和z,如果x.equals(y)回傳true,并且y.equals(z)也回傳true,那么x.equals(z)必須回傳true.
- 一致性(Consistence): 如果多次將物件與另一個物件比較,結果始終相同.只要未修改x和y的應用物件,x.equals(y)連續呼叫x.equals(y)回傳相同的值l.
- 非null(Non-null): 如果x不是null,y為null,則x.equals(y)必須為false
GetHashCode:
- 兩個相等物件根據equals方法比較時相等,那么這兩個物件中任意一個物件的hashcode方法都必須產生同樣的整數,
- 在我們未對物件進行修改時,多次呼叫hashcode使用回傳同一個整數.在同一個應用程式中多次執行,每次執行回傳的整數可以不一致.
- 如果兩個物件根據equals方法比較不相等時,那么呼叫這兩個物件中任意一個物件的hashcode方法,不一同的整數,但不同的物件,產生不同整數,有可能提高散串列的性能.
IEqualityComparer實作
下面我們創建一個學生類,從而進一步的實作我們物件資料的對比
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
通過如下代碼我們將通過distinct方法實作我們的過濾.
class Program
{
static void Main(string[] args)
{
List<Student> students = new List<Student>
{
new Student{ Name = "MR.A", Age = 32},
new Student{ Name = "MR.B", Age = 34},
new Student{ Name = "MR.A", Age = 32}
};
Console.WriteLine("distinctStudents has Count = {0}", students.Distinct().Count());//distinctStudents has Count = 3
Console.ReadLine();
}
}
我們需要達到的是忽略相同資料的物件,但是并沒有達到我們如期的效果.因為是distinct默認比較的是物件的參考...所以這樣達不到我們預期效果.那我們修改一下來實作我們預期效果.
在默認情況下Equals具有以下行為:
- 如果實體是參考型別,則只有參考相同時, Equals才會回傳true,
- 如果實體是值型別,則僅當型別和值相同時, Equals才會回傳true,
Distinct
通過使用指定的 IEqualityComparer
型別引數
- TSource source 的元素型別,
引數
- source IEnumerable
要從中移除重復元素的序列, - comparer IEqualityComparer
用于比較值的 IEqualityComparer ,
回傳
- IEnumerable
一個包含源序列中的非重復元素的 IEnumerable,
我們來看如下代碼片段
public class StudentComparator : EqualityComparer<Student>
{
public override bool Equals(Student x,Student y)
{
return x.Name == y.Name && x.Age == y.Age;
}
public override int GetHashCode(Student obj)
{
return obj.Name.GetHashCode() * obj.Age;
}
}
上述代碼片段如果兩個Equals回傳的true并且GetHashCode回傳相同的哈希碼,則認為兩個物件相等.
重寫Equals和GetHashCode
var stu1 = new Student { Name = "MR.A", Age = 32 };
var stu2 = new Student { Name = "MR.A", Age = 32 };
bool result = stu1.Equals(stu2); //false because it's reference Equals
上述代碼片段執行后結果非預期效果.我們將進一步的去實作代碼,以達到預期效果....
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public override bool Equals(object obj)
{
var stu = obj as Student;
if (stu == null) return false;
return Name == stu.Name && Age == stu.Age;
}
public override int GetHashCode()
{
return Name.GetHashCode() * Age;
}
}
var stu1 = new Student { Name = "MR.A", Age = 32 };
var stu2 = new Student { Name = "MR.A", Age = 32 };
bool result = stu1.Equals(stu2); //result is true
我們再使用LINQ Distinct方法進行過濾和查詢,同時將會檢查Equals和GetHashCode
List<Student> students = new List<Student>
{
new Student{ Name = "MR.A", Age = 32},
new Student{ Name = "MR.B", Age = 34},
new Student{ Name = "MR.A", Age = 32}
};
Console.WriteLine("distinctStudents has Count = {0}", students.Distinct().Count()); //distinctStudents has Count = 2
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/60034.html
標籤:其他
