Reputation: 5502
I'm making a few test cases and noticed I needed to check to see if MyObject was Equal to another MyObject.
I created my Equals methods like so:
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == typeof(MyObject) && Equals((MyObject) obj);
}
public bool Equals(MyObject other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(other.listItems, listItems);
}
public override int GetHashCode()
{
return (TimeBlocks != null ? TimeBlocks.GetHashCode() : 0);
}
There's a List called listItems that is not evaluating to true. The listItem is of another object type that does have an override on the Equals method.
How does the List decide if one list is equal to another?
Should I be checking each item against the other instead?
Upvotes: 0
Views: 176
Reputation: 71583
Well, first off, the overload for Equals that takes a MyObject is treating listItems
as static. If that's the case so be it, but my guess is that was a typo and that MyObject.listItems
should be other.listItems
instead.
Anyway. If listItems is a List<OtherObject>
, the List class itself doesn't override Equals, so it only uses the Object overload which compares hash codes, and for Object those hash codes are based on the object reference. So, two List variables will only be equal if they reference the same List.
To make it work the way you want, you'll need to loop through the list and compare items. Exactly how you do that depends on whether order matters:
//order-specific equality; true only if equal items are in the same order
public bool Equals(MyObject other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return other.listItems.Count == listItems.Count
&& listItems.Select((l,i)=>other.listItems[i] == l).All(b=>b);
}
//order-independent equality; true if all items in one are in the other in any order
public bool Equals(MyObject other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return other.listItems.Count == listItems.Count
&& listItems.Select((l,i)=>other.listItems.Contains(l)).All(b=>b);
}
The first method, given two equal lists, will be linear; the second will be N^2 complexity and while you could probably improve on that it would be complicated.
Upvotes: 1
Reputation: 17590
Is this what you are looking for: Enumerable.SequenceEqual
return other.listItems.SequenceEqual(listItems);
Upvotes: 1
Reputation: 52798
Have you tried the Enumerable.SequenceEqual()
method?
This will iterate over each item in the both of the List
's and check if each element is equal. It will use your objects' overridden Equals()
method.
Upvotes: 3