1

まず、比較したいことを言います: My Custom Object (Item) has List of strings taxids. あるリスト内のすべての文字列が別の文字列リストに含まれているかどうかを確認したい (taxids別のオブジェクト (アイテム) の別のリストにもなる)。

だから、これはクラスです:

public class Item
{
    public long taxid { get; set; }
    public long contentid { get; set; }
    public string taxname { get; set; }
    public IEnumerable<string> taxids { get; set; }
}

次に、これらはダミーのカスタム オブジェクトです。

    List<string> numbers = new List<string> { "5", "1" };
    List<string> numbers2 = new List<string> { "1", "2", "5","3","564" };

    Item pr = new Item();
    pr.contentid = 2517;
    pr.taxid = 2246;
    pr.taxids = numbers.AsEnumerable();
    pr.taxname = "nameItem1";
    List<Item> te = new List<Item>();
    te.Add(pr);
    IQueryable<Item> er = te.AsQueryable();

    Item pr2 = new Item();
    pr2.contentid = 0;
    pr2.taxid = 0;
    pr2.taxids = numbers2.AsEnumerable();
    pr2.taxname = "nameItem2";
    List<Item> te2 = new List<Item>();
    te2.Add(pr2);
    IQueryable<Item> er2 = te2.AsQueryable();

    IQueryable<Item> both = er.Intersect(er2, new ItemComparer());

ここでは、カスタムの comparer を使用しますItemComparer。このコードは次のとおりです。

public class ItemComparer : IEqualityComparer<Item>
{
    // items are equal if their names and item numbers are equal.
    public bool Equals(Item x, Item y)
    {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        //Check whether the items' properties are equal.
        return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.
    public int GetHashCode(Item item)
    {
        //Check whether the object is null
        if (Object.ReferenceEquals(item, null)) return 0;

        //Get hash code for the Name field if it is not null.
        int hashItemName = item.taxids == null ? 0 : item.taxids.GetHashCode();

        //Calculate the hash code for the item.
        return item.taxids.GetHashCode();

        //return "a".GetHashCode();
    }
}

問題は、変数bothが taxid フィールドに何もないことです。通常、「5」「1」のリストが必要です。

比較するときに hashCode が同じでなければならないことはわかっています。しかしtaxids、同じになることはありません。別の文字列リストで文字列を探すからです。

誰でもこの問題についてさらに助けてもらえますか?

(また、小さな質問: => のようなすべてのものに対して常に同じハッシュコードを返す場合、"a".GetHashCode()これは機能するかどうか?

前もって感謝します

4

2 に答える 2

2

あなたの問題は、双方向の平等がないことだと思います。オブジェクトがどちら側にあるかによって、pr と pr 2 は等しくありません。

どのオブジェクトが x で、どのオブジェクトが y であるかが比較子で保証されているかどうかはわかりません。最終的に比較対象になったらどうしますpr2か?x

ハッシュコードに関しては、あなたがやっているtaxids.GetHashCode()-それは単なるリストであり名前ではなく、同等性については何も教えてくれません.

于 2011-12-19T09:58:15.387 に答える
0
return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);

現在、同等性の比較では、コレクション内の要素のさまざまな順序は考慮されていません。大まかな回避策として、比較する前にそれらを注文するか、アイテムをハッシュセットに追加することをお勧めします。

return x.taxids.Intersect(y.taxids)
               .OrderBy(x => x)
               .SequenceEqual(x.taxids.OrderBy(x => x));

また、の適切な実装を提供する必要がGetHashCode()あります。デフォルトの実装はリスト内の実際のアイテムに依存しないためItem、コレクション内の同じ要素を持つ2つの異なるインスタンスに対して同じハッシュコードが生成されることはありません。あなたのケースに適した実装は、この他のSO投稿にあります。

于 2011-12-19T09:55:23.980 に答える