4

I have two lists of the same type.

One list is a deserialized json object loaded from a file and casted to the correct type.

The other is a list created of objects of the same type.

When I do List2.Except(List1) I expect to see everything in List2 that isn't in List1

In this case, List2 will have everything that List1 has and nothing more, so I expect to see a resulting Enumerable<T> of size 0, however I'm just seeing the entirety of List2 as if the comparison never happened.

IEnumerable<Review> newReviews = reviews.Except(savedRvReviews, new ReviewComparer());

I also tried using an EqualityComparer, code below:

public class ReviewComparer : IEqualityComparer<Review>
{
    public bool Equals(Review x, Review y)
    {
        return x.ReviewID == y.ReviewID;
    }

    public int GetHashCode(Review rv)
    {
        return EqualityComparer<Review>.Default.GetHashCode(rv);
    }
}

and got the same results.

Iterating through List2 and searching List1 via a LINQ query, I get the expected results of 0.

foreach (Review s in reviews)
{
    var m = from k in savedRvReviews
    where k.ReviewID == s.ReviewID
    select k;

    if (m.Count() == 0)
    {
        // Do something with new reviews
    }
}

Code for Review type:

public class Review : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    [Browsable(false)]
    public string ReviewID { get; set; }
    public string ProductID { get; set; }
    public DateTime DateSubmitted { get; set; }
    public string ReviewTitle { get; set; }

    [Browsable(false)]
    public string ReviewDescription { get; set; }
    public int ReviewMark { get; set; }

    [Browsable(false)]
    public bool Approved { get; set; }
}
5SK5
  • 159
  • 1
  • 1
  • 15
  • Why aren't you posting the code that your doing your Except in? – johnny 5 Apr 13 '16 at 18:14
  • i added it, but there's nothing special about it. – 5SK5 Apr 13 '16 at 18:15
  • if except is not working as expected and your using it properly, chances are you did not implement get hash code and override equals properly – johnny 5 Apr 13 '16 at 18:15
  • did you override equals and get hash code on your custom class? can you post the code for the Review class – johnny 5 Apr 13 '16 at 18:16
  • The code for the ReviewComparer is already at the bottom of my original post. – 5SK5 Apr 13 '16 at 18:17
  • No the code for the review class not the comparer, take a look at this https://msdn.microsoft.com/en-us/library/ms224763(v=vs.110).aspx, I'm pretty sure you actually need to override equals and get hashcode, I don't think you can use the Default.GetHashCode – johnny 5 Apr 13 '16 at 18:18
  • From Microsoft: To compare custom data types, implement the IEquatable generic interface and provide your own GetHashCode and Equals methods for the type. The default equality comparer, Default, is used to compare values of types that implement IEquatable. – Ziv Weissman Apr 13 '16 at 18:20
  • Yes, adding IEquatable interface to my `Review` class and then implementing the `Equals` method solved my problem. If you want to leave that as an answer I will accept it. – 5SK5 Apr 13 '16 at 18:22

2 Answers2

6

You have written a comparer where two reviews are equal when their IDs are equal, but you have not modified the hashcode. Two reviews that are equal should produce the same hashcode and your's don't.

the easiest way to make it happen would be to return the same hashcode for reviews that are equal. For example by using the hashcode of the only thing that makes two reviews equal, the ID:

public class ReviewComparer : IEqualityComparer<Review>
{
    public bool Equals(Review x, Review y)
    {
        return x.ReviewID == y.ReviewID;
    }

    public int GetHashCode(Review rv)
    {
        return rv.ReviewID.GetHashCode();
    }
}
nvoigt
  • 75,013
  • 26
  • 93
  • 142
0

Solution was adding IEquatable<Review> interface to my Review class and implementing the Equals method as such:

    public bool Equals(Review rv)
    {
        return this.ReviewID == rv.ReviewID;
    }

The rest of the code I posted worked fine, however this was the piece I was missing.

5SK5
  • 159
  • 1
  • 1
  • 15
  • This did not actually solve the problem, you change something else related to the hash code. See nvoigts answer. – usr Apr 13 '16 at 18:35