[英]EqualityComparer<T>.Default doesn't return the derived EqualityComparer
我有一個Person類,並創建了一個派生自EqualityComparer <Person>的相等競爭者類。 但默認的EqualityComparer不會調用我的相等比較器的Equals函數
根據MSDN EqualityComparer <T> .Default屬性 :
Default屬性檢查類型T是否實現System.IEquatable接口,如果是,則返回使用該實現的EqualityComparer。 否則,它返回一個EqualityComparer,它使用由T提供的Object.Equals和Object.GetHashCode的覆蓋。
在下面的(簡化)示例中,類Person不實現實現System.IEquatable <Person>。 所以我希望PersonComparer.Default會返回PersonComparer的實例。
但是沒有調用PersonComparer.Equals。 沒有調試輸出,返回值為false。
public class Person
{
public string Name { get; set; }
}
public class PersonComparer : EqualityComparer<Person>
{
public override bool Equals(Person x, Person y)
{
Debug.WriteLine("PersonComparer.Equals called");
return true;
}
public override int GetHashCode(Person obj)
{
Debug.WriteLine("PersonComparer.GetHasCode called");
return obj.Name.GetHashCode();
}
}
public static void Main()
{
Person x = new Person() { Name = "x" };
Person y = new Person() { Name = "x" };
bool b1 = PersonComparer.Default.Equals(x, y);
}
問題:我做錯了什么?
萬一你可能想知道為什么我不想實現IEquatable <Person>。
我的問題與字符串的比較相當。 有時你想要兩個字符串是相同的,如果它們是完全相同的字符串,有時你想忽略大小寫,有時你想把字符視為óò等所有就好像它們是字符o一樣。
就我而言:我將Person存儲在某個東西中,可能是一個數據庫,但它也可能是一個File或一個MemoryStream。 返回時,我得到一個標識符,如果數據庫當然是主鍵。 使用此鍵,我可以檢索具有相同值的對象。
我想在單元測試中測試這個:我把東西放進去,你應該得到一個可以用來檢索項目的密鑰。 唉,數據庫不返回相同的Person,而是返回Person的派生類(至少在使用EF 6時)。 所以我不能使用正常的IEquatable,如果對象不是同一類型,它應該返回false。 這就是為什么我想使用一個特殊的比較器,如果它們具有相同的屬性值,則聲明兩個Persons相等,即使它們都是Person的不同派生類。 與字符串比較器非常相似,它接受O和o以及ó相等
讓我們重新閱讀您添加的報價:
Default屬性檢查類型T是否實現
System.IEquatable
接口 ,如果是,則返回使用該實現的EqualityComparer。
因此, Default
屬性查找的實現IEqutable<T>
你的Person
不提供。
如果對象沒有實現IEquatable<T>
,那么:
否則,它返回一個EqualityComparer,它使用由T提供的Object.Equals和Object.GetHashCode的覆蓋。
這表明你到底為什么object.Equals
和object.GetHashCode
是被調用的。 您有兩種選擇,要么使用new PersonComparer().Equals()
,要么在您的類型上實現IEquatable<Person>
(如果可以實現這樣的單一實現)。
這是因為EqualityComparer<T>
的Default
屬性不返回PersonComparer
,而是返回ObjectEqualityComparer<T>
。 當您引用文檔時, ObjectEqualityComparer<T>
使用Equals
on Person
進行比較。
查看實際來源 。 在第89行,它返回ObjectEqualityComparer<T>
。
您的代碼實際上沒有任何問題,因為您可以看到當您實際嘗試在PersonComparer
的實例上運行代碼時:
bool b1 = new PersonComparer().Equals(x, y);
你混淆了一些東西,但這並不奇怪,因為每個人都必須承認.NET Framework在平等比較方面有太多可能性 。
只有當您想為特定情況指定特殊比較邏輯時,才應實現IEqualityComparer<T>
,例如,對於Dictionary<TKey, TValue>
。
EqualityComparer<T>
在.NET中是一個令人困惑的可覆蓋類型; 但是,並不打算覆蓋它,這樣做是沒有用的。 它提供了一個默認的比較泛型類型,它會叫你IEquatable<T>
如果你使用實施T
的List<T>
Contains
, IndexOf
等),或當T
是一本字典的鍵,你沒有將任何自定義IEqualityComparer
傳遞給字典。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.