簡體   English   中英

EqualityComparer <T> .Default不返回派生的EqualityComparer

[英]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.Equalsobject.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>如果你使用實施TList<T> ContainsIndexOf等),或當T是一本字典的鍵,你沒有將任何自定義IEqualityComparer傳遞給字典。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM