18

BCL にはIEqualityComparerを利用できる場所がいくつかあります。Enumerable.ContainsまたはDictionary Constructorのように。デフォルトのものに満足できない場合は、比較子を提供できます。

参照しているオブジェクトがコレクションに含まれているかどうかを知りたい場合があります。他の意味で「等しい」と見なされるものではありません。
問題は、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かなり満足しているようです.

4

2 に答える 2

17

私の知る限り、BCLはIEqualityComparer<T>、.NET 4.0の時点で、参照と同等で実装されるパブリックタイプを公開していません。

ただし、これを行う内部タイプは次のようにたくさんあるようです。

  • System.Dynamic.Utils.ReferenceEqualityComparer<T> (System.Core内)
  • System.Xaml.Schema.ReferenceEqualityComparer<T> (System.Xaml内)。

リフレクターを使用したこれら2つのタイプの実装を確認しましたが、レイジー初期化を使用しないことを除けば、どちらも実質的に同じ方法で実装されているように見えることを知っていただければ幸いです。静的インスタンスの場合(型の静的コンストラクターで作成します)。

実装で考えられる唯一の「問題」は、レイジー初期化がスレッドセーフではないことですが、インスタンスは「安価」であり、どの状態も保持していないため、バグやメジャーが発生することはありません。パフォーマンスの問題。ただし、シングルトンパターンを適用する場合は、適切に実行する必要があります。

于 2011-02-04T18:09:19.280 に答える
2

回避策が見つからなかったため、このソリューションも使用することになります。

非スレッドセーフな実装を修正するには、静的初期化子を簡単に使用できます。

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

(賛成票を投じたスレッドへのコメントの代わりに答えて申し訳ありません。私はまだコメント権のない新しいアカウントを持っています)。

于 2015-12-16T07:13:30.087 に答える