Question

Firstly, I will say what I want to compare the following: My Custom Object (Item) has a List of strings taxids. I want to look if all the strings in one List occur in another list of strings (will be also another taxids of another Object (Item).

So, this is the class:

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

Then these are the dummy custom objects:

    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());

Here I use a custom comparer ItemComparer. Here is the code for this:

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();
    }
}

The problem is that variable both has nothing in the taxids field, normally I should have a list of "5" "1".

I know that the hashCode must be the same when comparing. but taxids will be never the same. Because we look for strings in another list of strings.

Anybody can further help me with this problem?

(Also a small question: If I return always the same hashcode for everything like "a".GetHashCode() => should this work or not?

Thanks in advance

Was it helpful?

Solution

I think your problem is that you do not have bidirectional equality. depending on which side your object is, pr and pr 2 are not equal.

I am uncertain whether there is a guarantee which object is x and which is y in your comparer. What if pr2 ends up to be x in your comparer?

with regard to the hash code, you are doing taxids.GetHashCode() - that is just a list and not a name and won't tell you anything about equality.

OTHER TIPS

return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);

Your equality comparison does currently not take into account the different order of elements in the collections. As a crude workaround you could order them before comparing, or better add the items to a hashset:

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

Also you have to provide an appropriate implementation of GetHashCode(), the default implementation is not dependent on the actual items in the list, so wouldn't result in the same hashcode for two different Item instances that have the same elements in the collection. A more appropriate implementation for your case can be found in this other SO post.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top