1

この質問をあまり繰り返さないでください。しかし、私はすでに検索を行っており、結果は空でした。したがって、タイプ T の 2 つの EntityCollections があり、それぞれに共通の項目を見つけたいと考えています。キャッチ?1 つを除くすべてのフィールドが一致する必要があります。たとえば、タイプ T がタイプ CustomSet であり、CustomSet にフィールド F1、F2、F3 および FK フィールド OtherId が含まれている場合、F1、F2、および F3 は一致する必要があり (文字列、int、実際には何でもかまいません)、OtherId は決して一致しません。マッチ。私の現在の実装:

var intersections = source.Intersect(destination).ToList();

フィールド F1、F2、および F3 が一致する場合でも、OtherId 列が他のコレクションで一致することはないため、結果は得られません。そこで、次のような IEqualityComparer のカスタム実装を提案します。

var intersections = source.Intersect(destination, new EntityCollectionComparer<T>()).ToList();

public class EntityCollectionComparer<T> : IEqualityComparer<T>
{
    #region IEqualityComparer<T> Members

    public bool Equals(T x, T y)
    {
        if (x.Equals(y))
            return true;
        else
            return false;
    }

    public int GetHashCode(T obj)
    {
        if (obj is CustomSet)
        {
            CustomSet temp = obj as CustomSet;

            return (temp.F1.GetHashCode() ^ temp.F2.GetHashCode() ^ temp.F3.GetHashCode());
        }
        return obj.GetHashCode();
    }

今、私はこれをテストしているだけなので、渡される obj は CustomSet 型です。これを適切に機能させることができれば、他の型に必要な if ステートメントを追加します。Intersect 拡張機能は、Equals の代わりに GetHashCode を使用して項目を比較することを知っています。これが、EntityCollections の Intersect 拡張機能以外では、このクラスが呼び出されることはないため、equals の内容を本当に気にしない理由です。問題は、これは機能しないということです。私のテスト セットでは、「ソース」コレクションに 28 個のアイテムがあり、「宛先」コレクションに 28 個のアイテムがあり、すべてのフィールドが一致していることがわかります (もちろん、OtherId フィールドを除く)。GetHashCode コードは 56 回ループし、各セットの 28 アイテムすべてのハッシュ コードを一致させることができましたが、「交差」は 0 カウントでした。私が間違っていること、または欠けていることはありますか?ありがとう。}

4

1 に答える 1

1

これはあなたの問題です:

Intersect 拡張機能は、Equals の代わりに GetHashCode を使用して項目を比較することを知っています。そのため、このクラスが呼び出されることは決してないため、EntityCollections の Intersect 拡張機能のために、equals の内容を本当に気にしません。

それは単に真実ではありません。GetHashCode値をバケット化する最初の「迅速な」方法として使用されますEqualsが、同じハッシュを持つアイテムに対して引き続き呼び出されます。そうしないと、それらが等しいことを知ることができません。

これが、ハッシュ テーブルなどが常に機能する方法です。ハッシュは、パフォーマンス上の理由から実行可能な場合、等しくない値に対して異なる必要がありますが、衝突は許可されます。

于 2011-01-24T17:16:32.360 に答える