Reputation: 2199
I have an IEqualityComparer in c#:
public class ScheduledTimeComparer : IEqualityComparer<ScheduledTime>
{
public bool Equals(ScheduledTime x, ScheduledTime y)
{
if (x == y) return true;
if (x == null) return false;
return GetHashCode(x) == GetHashCode(y);
}
public int GetHashCode(ScheduledTime schedule)
{
return schedule.Start.GetHashCode() ^ schedule.End.GetHashCode();
}
}
public class ScheduledTime
{
public int Start { get; set; }
public int End { get; set; }
}
I have the following 2 list of ScheduledTimes objects:
List1 = [{ Start = 60, End = 120 }]
List2 = [{ Start = 180, End = 240 }, { Start = 60, End = 120 }]
Now when i use the above mentioned equality comparer like:
//Count should be greater than 0 because both List1 and List2 are not equal
var equal = List1.Except(List2, new ScheduledTimeComparer()).Count == 0;
The Count is always zero, What i am doing wrong ?
Upvotes: 1
Views: 873
Reputation: 48096
Your comparison works fine, the problem is that you're misusing Except
var equal = List1.Except(List2, new ScheduledTimeComparer()).Count == 0;
This is giving you items in list1 that aren't in list2. List 1 is a subset of list2 so you get nothing back. If you change it to;
var dif = List2.Except(List1, new ScheduledTimeComparer()).ToList();
dif.AddRange(List1.Except(List2, new ScheduleTimeComparer());
if (dif.Count() > 0)
// the lists are different
Then you will get back 1 item and it will work as you expected.
Upvotes: 2
Reputation: 56536
List1.Except(List2...
looks for items that are in List1
but not in List2
. It sounds like you want to know if the lists are equal to each other. Here is one way to do that, using SetEquals
:
var set1 = new HashSet<ScheduledTime>(List1, new ScheduledTimeComparer());
bool equal = set1.SetEquals(List2);
Also, your Equals
and GetHashCode
implementations are broken. In Equals
, instead of just comparing hash codes, you need to compare values to get accurate answers. And using XOR (^
) in GetHashCode
is weak, e.g. anything with Start == End
will hash to 0 and both of your examples hash to the same value, 68
. A better option is to use multiplying by primes and addition to work out the hash codes. Also, since int.GetHashCode()
returns the int
itself, I omitted it. This will work better:
public class ScheduledTimeComparer : IEqualityComparer<ScheduledTime>
{
public bool Equals(ScheduledTime x, ScheduledTime y)
{
if (x == y) return true;
if (x == null) return false;
return x.Start == y.Start && x.End == y.End;
}
public int GetHashCode(ScheduledTime schedule)
{
unchecked
{
return schedule.Start * 31 + schedule.End;
}
}
}
Upvotes: 2
Reputation: 1726
List1.Except(List2, new ScheduledTimeComparer())
means List1 \ List2 in group terms; that is, take all the elements in List1 not preset in List2. There are no such elements, so the returned result is empty.
Perhaps what you wanted to do is:
List2.Except(List1, new ScheduledTimeComparer())
Which would return a single result.
Upvotes: 0
Reputation: 144136
The count should be zero since Except
is set difference and there is an element in List2
equal to the single element in List1
. The output sequence contains the elements of List1
not in List2
, and there are no such elements using your comparer.
Upvotes: 1