簡體   English   中英

使用IEqualityComparer <T> 接口和EqualityComparer <T> C#中的類

[英]Using of IEqualityComparer<T> interface and EqualityComparer<T> class in C#

我正在編寫循環鏈表,使用本文作為幫助。

在一個函數中,在此列表中搜索具有給定值的節點

    public Node<T> Find(T item)
    {
        Node<T> node = FindNode(head, item);
        return node;
    }

    Node<T> FindNode(Node<T> node, T valueToCompare)
    {
        Node<T> result = null;
        if (comparer.Equals(node.Value, valueToCompare))
            result = node;
        else if (result == null && node.Next != head)
            result = FindNode(node.Next, valueToCompare);
        return result;
    }

作者使用IEqualityComparer<T> comparer對象,該對象在其中一個構造函數中使用屬性EqualityComparer<T>.Default進行初始化。 你能解釋一下在這里使用這些接口( IEqualityComparer<T> )和類( EqualityComparer<T> )的想法嗎? 我讀過MSDN,但我不理解工作和使用它們的原理。

IEqualityComparer<in T>是一個接口,用於處理集合的相等比較。 您的收藏會將等同性比較委托給此界面。 您可能會問,為什么不直接調用Equals方法?

因為可以有幾種可能的比較。 讓我們舉一個簡單的例子: "Abc""ABC"相等? 這取決於。 "Abc".Equals("ABC") == false但是如果你想要不區分大小寫怎么辦?

這就是為什么您的集合應該相等比較委托給不同的類。 通過編寫類,您將尊重單一責任原則:您的集合知道如何存儲項目,並且相等比較器知道它們是否相等。

集合的示例:

var caseSensitive = new HashSet<string>(StringComparer.Ordinal) // The default anyway
{
    "Abc", "ABC"
};

var caseInsensitive = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
    "Abc", "ABC"
};

結果將是:

caseSensitive.Count == 2
caseInsensitive.Count == 1

caseSensitive.Contains("aBc") == false
caseInsensitive.Contains("aBc") == true

在這里,您使用相同的HashSet類有兩個完全不同的set語義。

現在, IEqualityComparer<in T>什么?

  • bool Equals(T x, T y); :此方法正如您所期望的那樣:如果x應該被視為等於y則返回true 就像數學上的平等一樣,它必須是:
    • 反身: Equals(x, x) == true
    • 對稱: Equals(x, y) == Equals(y, x)
    • 傳遞:如果Equals(x, y) && Equals(y, z)Equals(x, z)
  • int GetHashCode(T obj); 這個可能更難以正確。 對於每個obj ,它應返回具有以下屬性的哈希碼:
    • 它永遠不應該改變
    • if Equals(x, y)GetHashCode(x) == GetHashCode(y)
    • 應該盡可能少的碰撞

注意,這並不意味着如果GetHashCode(x) == GetHashCode(y)Equals(x, y) 兩個對象可以具有相同的哈希碼但是不相等(畢竟最多可以有0xFFFFFFFF哈希碼)。

集合通常使用哈希代碼來組織其項目。 例如, HashSet將知道如果兩個對象不具有相同的哈希碼,則它們將不相等,因此可以相應地組織其桶。 哈希碼只是一種優化。

現在,什么是EqualityComparer<T>.Default 它是IEqualityComparer<T>一個IEqualityComparer<T>快捷方式,它將使用對象自己的EqualsGetHashCode函數。 這是一個很好的默認值,因為這是你想要在大多數時間做的事情:雖然字符串可以有多個自然比較類型,但例如整數不是這種情況。

EqualityComparer<T>.Default將處理幾個特殊情況:

  • 如果T is IEquatable<T> ,它將使用IEquatable<T>接口
  • 如果T is Nullable<U>U is IEquatable<U>則它將正確處理該情況
  • 它將針對一些特殊情況進行優化: byte[]和int-basd Enum

暫無
暫無

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

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