List.Except is not working

c#, linq, list

Solution

In order to make `Except` method working as expected, the class `AssignUserViewModel` must have `GetHashCode` and `Equals` methods correctly overridden.

For example, if `AssignUserViewModel` objects are uniquely defined by their `Id`, you should define the class in this way:

class AssignUserViewModel
{
    // other methods...


    public override int GetHashCode()
    {
        return this.Id.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        if (!(obj is AssignUserViewModel))
            throw new ArgumentException("obj is not an AssignUserViewModel");
        var usr = obj as AssignUserViewModel;
        if (usr == null)
            return false;
        return this.Id.Equals(usr.Id);
    }
}

Otherwise, if you can't/don't want to change the class implementation, you can implement an `IEqualityComparer<>` and pass it to the `Except` method, e.g. :

class AssignUserViewModelEqualityComparer : IEqualityComparer<AssignUserViewModel>
{
    public bool Equals(AssignUserViewModel x, AssignUserViewModel y)
    {
        if (object.ReferenceEquals(x, y))
            return true;
        if(x == null || y == null)
            return false;
        return x.Id.Equals(y.Id);
    }

    public int GetHashCode(AssignUserViewModel obj)
    {
        return obj.Id.GetHashCode();
    }
}

then your last line would become:

assignUsers = assignUsers.Except(assignedUsers, new AssignUserViewModelEqualityComparer()).ToList();

Problem

I try to subtract 2 lists like below code, `assignUsers` has got 3 records and `assignedUsers` has got 2 rows. After `Except` method I still get 3 rows, although I should get 1 record because 2 rows in `assignedUsers` is similar to `assignUsers` ``` var users = accountApp.GetUsersByAccountId(context.GetUserData().AccountId); List<AssignUserViewModel> assignUsers = Mapper.Map<List<AssignUserViewModel>>(users).ToList(); var mailUsers = mailApp.GetMailAssignedByMailId(id).Select(m => new { m.UserId, m.User.Name }).ToList(); List<AssignUserViewModel> assignedUsers = mailUsers.Select(Mapper.DynamicMap<AssignUserViewModel>).ToList(); assignUsers = assignUsers.Except(assignedUsers).ToList(); ```

Original source