2011-02-04 71 views
18

BCL有幾個地方可以使用IEqualityComparer。像Enumerable.ContainsDictionary Constructor。如果我對default之一不滿意,我可以提供我的比較器。.NET中是否有任何一種「ReferenceComparer」?

有時候我想知道該集合是否包含那個對象,我有參考。不是那種在其他意義上被認爲「相等」的人。
現在的問題是:BCL中是否存在標準相等比較器,僅依賴於ReferenceEquals方法?

,我寫我自己的一個是這樣的:

class ReferenceComparer<T> : IEqualityComparer<T> where T : class 
{ 
    private static ReferenceComparer<T> m_instance; 

    public static ReferenceComparer<T> Instance 
    { 
     get 
     { 
      return m_instance ?? (m_instance = new ReferenceComparer<T>()); 
     } 
    } 

    public bool Equals(T x, T y) 
    { 
     return ReferenceEquals(x, y); 
    } 

    public int GetHashCode(T obj) 
    { 
     return RuntimeHelpers.GetHashCode(obj); 
    } 
} 

我也沒搞也沒有考慮很多的情況下測試,但它似乎使Enumerable.ContainsDictionary很高興。

+2

不幸的是,所有這些集合都是以Java風格的方式編寫的,需要編寫一個實現特定接口的類。如果只允許你傳入一個委託來指定比較運算符,那麼你可以直接傳遞`object.ReferenceEquals`。我想這是因爲需要兩種方法(比較和散列碼)。 – 2011-02-04 18:24:52

+0

但據我瞭解,`IEqualityComparer`的Java對應語句沒有`GetHashCode`,因此如果Java支持委託,它可以作爲Java代理實現。 – Gabe 2011-02-04 18:35:31

回答

17

據我所知,BCL沒有公開任何實現IEqualityComparer<T>的公共類型與.NET 4.0的引用相等。

然而,看起來確實是一串內部類型的做到這一點,如:

  • System.Dynamic.Utils.ReferenceEqualityComparer<T> (在System.Core程序)
  • System.Xaml.Schema.ReferenceEqualityComparer<T> (在System.Xaml)。

我看了一下這兩種類型的反射器的實現,你會很高興地知道,他們兩個出現的方式,實際上是相同到你的實施,除了它們不會爲靜態實例使用延遲初始化(它們會在靜態構造函數中爲該類型創建它)。

我認爲你的實現唯一可能的'問題'是懶惰初始化不是線程安全的,但由於實例是'便宜',並沒有堅持任何狀態,不應該創建任何錯誤或主要性能問題。如果你想執行單身模式,但你必須做到這一點。

2

我最終也使用此解決方案,因爲我無法找到任何解決方法。

要修復非線程安全實現,可以很容易地使用靜態初始化程序。

public static ReferenceComparer<T> Instance => new ReferenceComparer<T>(); 

(抱歉的答案,而不是到上投螺紋評論,我有一個新的帳戶沒有評論的權利,還)。