2

非ジェネリックを実装する必要がGetHashCodeありEquals、クラスが実装する場合はどうなりIEqualityComparer<T>ますか?

更新: 私の希望は、MSがを導入したときにコレクションの実装を更新することでしたIEqualityComparer<T>。そのDictionaryため、他のコレクションクラスは、クラスがIEqualityComparer<T>ジェネリックメソッドGetHashCodeを実装および使用していないかどうか、およびEqualsそのインターフェイスが実装されていない場合にのみ内部的にチェックすると思いました。コレクションのサポートがなければ、そのインターフェースにはほとんど価値がありません。

Update2:ILSpyを使用して チェックDictionary.FindEntry(TKey key)しました。使用しますIEqualityComparer<TKey>comparer以下の変数)。GetHashCode実際、私は一般的ではない関数や関数の使用をまったく見つけませんでしEqualsた。

int num = this.comparer.GetHashCode(key) & 2147483647;
for (int i = this.buckets[num % this.buckets.Length]; i >= 0; i = this.entries[i].next)
{
    if (this.entries[i].hashCode == num
                && this.comparer.Equals(this.entries[i].key, key))
    {
        return i;
    }
}

したがって、私のクラスは、IEqualityComparer<T>で適切に使用するために実装する必要があるだけのようDictionaryです。

万が一の場合に備えて、ジェネリックではない関数を実装しても害はないことを理解しています。

しかし、それが価値をもたらさないのであれば、私たちは時間を費やすべきでしょうか?

私の質問をより具体的にします:

非ジェネリックを実装する必要がGetHashCodeありEquals、クラスが実装する場合IEqualityComparer<T>

  1. コードでジェネリックではないコレクションを使用していません
  2. GetHashCodeサードパーティのコードは、私のコードのEqualsメソッドを呼び出しません。

Microsoftコードが正しく機能するには、非汎用バージョンが必要ですか?

Update3:わかったと思います。IEqualityComparer<T>それは私のクラス内で実装されると思いました。その場合、メソッドの汎用バージョンと非汎用バージョンが1か所にあります。それはどのIEqualityComparer<T>ように使用されるべきではありません。別のクラスとして実装し、パラメータとして使用する必要があります。

みなさん、ありがとうございました。

4

3 に答える 3

3

場合によります。 IEqualityComparer<T>タイプの2つのインスタンスを比較するために使用さTれ、通常は別の比較クラスによって実装されます。通常、これをクラスタイプに実装することはありませんTこれは、彼をサポートするタイプで使用するための代替比較を提供することを目的としています。

これをクラス自体に実装する場合は、通常、を実装しIEquatable<T>ます。

そうは言っても、をオーバーライドすると便利なことがよくあります。これは、メソッドを使用してを実装Object.Equalsできるため、通常は非常に簡単です。これにより、実装が「安価」になります。使用される可能性があるように、それは平等に一貫した意味を提供するので、一般的に実装することは良い考えです。IEquatable<T>.EqualsObject.EqualsObject.Equals

オブジェクトがaDictionary<T,U>やaなどのハッシュのキーとして使用されるHashSet<T>場合は、をオーバーライドする必要がありますGetHashCode。このように使用される可能性さえある場合は、このメソッドをオーバーライドすると便利です。GetHashCode通常、後で型をキーとして使用する場合に備えて、等式を実装するときはいつでもオーバーライドすると便利です。

于 2012-06-09T19:30:58.050 に答える
2

IEqualityComparerは、GetHashCodeのデフォルトの実装を置き換えることを目的としており、すべての.NETオブジェクトがすでに持っているものと同じです。このインターフェースは、ディクショナリと(ハッシュ)セットによってのみ使用され、オブジェクトがデフォルトで使用するのとは異なるハッシュおよび比較スキームを使用します。

オブジェクトがDictionariesとHashTablesでキーとして使用されている場合は、最初にEqualsとGetHashCodeをオーバーライドして、Sets / Dictionarysがオブジェクトのデフォルトの比較子(EqualityComparere.Defaultと呼ぶもの)を使用できるようにする必要があります。とりあえず。

IEqualityComparerを介して外部比較子を提供する唯一の理由は、別の比較スキームを使用することです。たとえば、文字列の場合、大文字と小文字を区別するバリアントと大文字と小文字を区別しないバリアントの間でBCLStringComparerクラスから選択できます。

Update1

この質問の目的は、Listおよびその他のコレクションが、オブジェクトによって提供されるものではなく、常にデフォルトの比較子を使用する理由でした。オブジェクトがすでにEqualsとGetHashCodeを実装している場合、オブジェクトが同時にIEqualityComparerも実装しているのに、なぜListはそれらを使用しないのですか?Listは、別の比較子を使用できるctorを提供していないため、デフォルトの比較子を使用する必要があります。

ただし、別のものを使用したい場合は、いつでもLINQを使用できます。これにより、特定の方法について独自の比較子を明示的に渡すことができるため、この問題が修正されます。たとえば、 Enumerable.Containsには、独自の比較子を渡すことができるオーバーロードがあります。

MSDNサンプルから:

Product[] fruits = { new Product { Name = "apple", Code = 9 }, 
                       new Product { Name = "orange", Code = 4 }, 
                       new Product { Name = "lemon", Code = 12 } };

Product apple = new Product { Name = "apple", Code = 9 };
Product kiwi = new Product {Name = "kiwi", Code = 8 };

ProductComparer prodc = new ProductComparer();

bool hasApple = fruits.Contains(apple, prodc);
bool hasKiwi = fruits.Contains(kiwi, prodc);
于 2012-06-09T19:33:15.817 に答える
1

私があなたを正しく理解していて、実装するIEqualityComparer場合にも実装する必要があるかどうかを尋ねている場合IEqualityComparer<T>、答えはそうする必要はないということですが、おそらくそれは良い考えです。比較対象を既存のコードとの互換性を高めるだけです。

于 2012-06-09T19:33:28.910 に答える