質問

デフォルトはありますか IEqualityComparer<T> を使用する実装 ReferenceEquals?

EqualityComparer<T>.Default ObjectComparer を使用します。 object.Equals(). 。私の場合、オブジェクトはすでに実装されています IEquatable<T>, 、これは無視し、オブジェクトの参照のみで比較する必要があります。

役に立ちましたか?

解決

デフォルトの実装がない場合に備えて、これは私自身のものです。

280Z28による編集:使用の理論的根拠 RuntimeHelpers.GetHashCode(object), 、おそらくこれまで見たことがない人も多いでしょう。:) この方法には 2 つの効果があり、 正しい この実装を呼び出します。

  1. オブジェクトが null の場合は 0 を返します。以来 ReferenceEquals これは null パラメータに対して機能するため、比較器の GetHashCode() の実装も同様です。
  2. それは呼びます Object.GetHashCode() 非仮想的に。 ReferenceEquals 特にオーバーライドを無視します Equals, したがって、GetHashCode() の実装では、ReferenceEquals の効果に一致する特別なメソッドを使用する必要があります。これはまさに RuntimeHelpers.GetHashCode の目的です。

【エンド280Z28】

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

/// <summary>
/// A generic object comparerer that would only use object's reference, 
/// ignoring any <see cref="IEquatable{T}"/> or <see cref="object.Equals(object)"/>  overrides.
/// </summary>
public class ObjectReferenceEqualityComparer<T> : EqualityComparer<T>
    where T : class
{
    private static IEqualityComparer<T> _defaultComparer;

    public new static IEqualityComparer<T> Default
    {
        get { return _defaultComparer ?? (_defaultComparer = new ObjectReferenceEqualityComparer<T>()); }
    }

    #region IEqualityComparer<T> Members

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

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

    #endregion
}

他のヒント

私はそれはIEqualityComparer<in T>インターフェイス上contravarianceに非ジェネリックのおかげになることで、簡素化.Net4.0 +に以前の回答の実装を更新するための時間だと思った。

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

public sealed class ReferenceEqualityComparer
    : IEqualityComparer, IEqualityComparer<object>
{
    public static readonly ReferenceEqualityComparer Default
        = new ReferenceEqualityComparer(); // JIT-lazy is sufficiently lazy imo.

    private ReferenceEqualityComparer() { } // <-- A matter of opinion / style.

    public bool Equals(object x, object y)
    {
        return x == y; // This is reference equality! (See explanation below.)
    }

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

これが唯一のケースは前にあったように、すべてのリファレンスの同一性は、それぞれのタイプのTに1つの代わりにチェックするためのインスタンスを存在する必要があります。

また、あなたはTあなたがこれを使用するたびに指定する必要がないため、タイピングを節約!

<時間>

共変性と反変性するの概念に精通していない人のために明らかにするために..ます。

class MyClass
{
    ISet<MyClass> setOfMyClass = new HashSet<MyClass>(ReferenceEqualityComparer.Default);
}

...うまく動作します。これは、 のない、例えばこれらに限定されていますHashSet<object>又は(.Net4.0で)類似している。

<時間>

また疑問誰にとってなぜx == yoperatorは、それがコンパイル時に解決されることを意味静的方法であり、コンパイル時に、xおよびyがので、ここでそれが解決タイプ==であるためobjectは、基準等価です==objectoperator - の本当のの参照の等価方法です。 (オブジェクトへのリダイレクトは、オペレータに等しい単に実際Object.ReferenceEquals(object, object)方法がある。)

ここではC#6のための単純な実装です。

public sealed class ReferenceEqualityComparer : IEqualityComparer, IEqualityComparer<object>
{
    public static ReferenceEqualityComparer Default { get; } = new ReferenceEqualityComparer();

    public new bool Equals(object x, object y) => ReferenceEquals(x, y);
    public int GetHashCode(object obj) => RuntimeHelpers.GetHashCode(obj);
}
<時間>

編集(あなたが以下のコメントに興味がなければ、これを読む必要はありません)。

@AnorZakenはここnew改質剤の3つの文字に多くのパラグラフを捧げました。さんがまとめてみましょう。

単一の定義されたインスタンスEquals(object,object)方法はこのタイプ、Equalsそのジェネリック相手IEqualityComparerのための2つの宣言されたインターフェースのIEqualityComparer<object>方法を実装します。署名が同一であるので、この定義を満たす両方のインタフェース。

インスタンスメソッドReferenceEqualityComparer.Equals(object,object)静的 object.Equals(object,object)方法を非表示にします。

newがなければ、コンパイラはこれについて警告しています。これは実際に何を意味するのでしょうか?

それはあなたが静的object.Equalsメソッドを呼び出したい場合は、あなたがReferenceEqualityComparerのインスタンスの上でそれを呼び出すことができないことを意味します。これは大したことですか?

はありません。実際には行動を希望です。それはあなたがobject.Equals(a,b)を呼び出したい場合は、このようなReferenceEqualityComparer.Default.Equals(a,b)ようなコードを経由してそれを行うことができないことを意味します。このコードは明らかにの参照の平等を要求している - 誰も合理的にそれがデフォルト/値の平等を行うことを期待しないであろう。なぜあなたはとにかくより明示的object.Equals(a,b)をコーディングしないのでしょうか?だから、newの使用は賢明かつ望ましい行動を提供し、警告なしでコンパイルすることができます。

他にどのようにあなたは警告を抑制することができますか?あなたは#pragma warning disable 108 / #pragma warning restore 108を使用する場合、結果はあなたのコードにたくさんより多くのノイズを追加しました除き、newを使用するのと同じです。 newで十分と他の人に、より明確に意図を説明します。

別の方法として次の2つのインターフェイスEqualsメソッドの明示的な実装を使用することができますが、あなたはReferenceEqualityComparer.Default.Equals(a,b)を使用した場合、あなたはすべての基準平等を持っていないでしょう。

静的メソッドは、型指定ではなく、インスタンス指定子から逆参照されているため、

は、実際には、インスタンスメソッドと静的メソッドを隠蔽することはめったに問題ではありません。それはあなたがFoo.StaticMethod()ないnew Foo().StaticMethod()を使用し、です。インスタンスからの静的メソッドを呼び出すと、最悪の場合、誤った/最高で不要と誤解を招く恐れがあります。

さらに、平等する比較器のために、あなたはめったに自分の具体的な種類を直接使用しません。むしろ、あなたは、このようなコレクションとしてのAPIでそれらを使用します。

これはされたがだから面白いと議論を混乱の回で、それはかなり無益だっます。

MicrosoftはObjectReferenceEqualityComparerSystem.Data.Entity.Infrastructureを提供しています。 ただ、比較演算子としてObjectReferenceEqualityComparer.Defaultを使用します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top