简体   繁体   中英

IEnumerable.Except() not excluding

I have two arrays. The first holds all members, the second holds all claimed members. I'm trying to get only the unclaimed members using an except, but the resulting array includes all members (an exact copy of the first array).

var junior_handler_All = db2.junior_handler.Include(j => j.person).Include(j => j.status).ToArray();

var junior_handler_Claimed = db.junior_handler.Include(j => j.person).Include(j => j.status).ToArray();

var junior_handler_Unclaimed = junior_handler_All.Except(junior_handler_Claimed).ToArray();

I have also tried getting the unclaimed members using a where query with the same results.

var junior_handler_Unclaimed = junior_handler_All.Where(i => !junior_handler_Claimed.Contains(i.Junior_Handler_ID.ToString()));

Any ideas why either of these aren't working?

The way Except and Contains compare elements is by calling GetHashCode() and - if that hash is equal - calling Equals to check if two elements are equal.

So if you apply this to reference types that do not have an own implementation of GetHashCode() and Equals() , this comparison results in a simple reference equality check.

You probably don't want to compare the references of your objects, but some kind of ID. So you have two options:

You can either override GetHashCode() and Equals() in your class:

public class Person
{
    public int ID { get; set; }

    public override bool Equals(object o)
    {
        return ID == (o as Person)?.ID;
    }
    public override int GetHashCode()
    {
        return ID;
    }
}

or you implement an IEqualityComparer<Person> like this:

public class Comparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return x.ID == y.ID; // or whatever defines your equality
    }
    public int GetHashCode(Person obj)
    {
        return obj.ID; // or whatever makes a good hash
    }
}

and provide an instance of this comparer to Except :

var junior_handler_Unclaimed =
     junior_handler_All.Except(junior_handler_Claimed, new Comparer()).ToArray();

You need to update your class to implement IEquatable and/or override Equals and GetHashCode.

References:

MSDN on Except:

Produces the set difference of two sequences by using the default equality comparer to compare values

MSDN on default equality comparer:

The Default property checks whether type T implements the System.IEquatable interface and, if so, returns an EqualityComparer that uses that implementation. Otherwise, it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM