Reputation: 39384
I have the following:
var a = new List<OrderRule> {
new OrderRule("name", OrderDirection.Ascending),
new OrderRule("age", OrderDirection.Descending)
};
var b = new List<OrderRule> {
new OrderRule("name", OrderDirection.Ascending),
new OrderRule("age", OrderDirection.Descending)
};
var r = a.Equals(b);
The r variable is false even if the two lists include items which are equal to each other. The OrdeRule class implements IEquality. Note that two OrderRules are equal when both Direction and Property are equal.
public enum OrderDirection { ASC, DESC }
public class OrderRule : IEquatable<OrderRule> {
public OrderDirection Direction { get; }
public String Property { get; }
public OrderRule(String property, OrderDirection direction) {
Direction = direction;
Property = property;
}
public Boolean Equals(OrderRule other) {
if (other == null)
return false;
return Property.Equals(other.Property) && Direction.Equals(other.Direction);
}
public override Boolean Equals(Object obj) {
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != GetType())
return false;
return Equals(obj as IncludeRule);
}
public override Int32 GetHashCode() {
return HashCode.Of(Property).And(Direction);
}
}
What am I missing?
Upvotes: 5
Views: 4376
Reputation: 29222
Checking to see if two lists are equal doesn't mean checking to see if they both contain the same items.
If you do this:
var a = new List<OrderRule>();
var b = new List<OrderRule>();
var r = a.Equals(b); //false
r
will always be false, even if the two lists have the same items in them. That's because you're not checking the contents of the lists. You're actually checking to see if both a
and b
refer to the same object. But a
is one object and b
is another.
If you did this, r
would be true:
var a = new List<OrderRule>();
var b = a;
var r = a.Equals(b) //true
If you have two lists and you want to see if they contain the same items in the same order, you could do this:
var r = a.SequenceEquals(b);
In the example in your question r
would be true
because you're overriding Equals
on OrderRule
, so the items in the one list are considered "equal" to the items in the other.
Got it - your equality check in OrderRule
is broken.
public override Boolean Equals(Object obj) {
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != GetType())
return false;
return Equals(obj as IncludeRule);
}
I think instead of return Equals(obj as IncludeRule)
you mean return Equals(obj as OrderRule)
.
Upvotes: 9
Reputation: 50190
your code is testing to see if they are the same list. not if they have the same contents.
a.Equals(b); // false
var d = a;
d.Equals(a); // true
if you want to compare the contents then use linq's SequenceEqual
https://msdn.microsoft.com/en-us/library/bb348567(v=vs.100).aspx
Upvotes: 4
Reputation: 21
First whenever one uses new
keyword or creates a new object the reference or the address of the object is stored in the variable.
Also equals compares the value of the variable.
Now you have overrided the equals function of the OrderRule
. So if you do equals on two OrderRule
you will get the result as you compare it inside the overrided equals function.
But now think about this What is List<OrderRule>
its nothing but a generic class. So again the equals will check the value of the variable which contains the reference and since they are different you will not get true when you compare them. Also List implements the equals same as that of the object its not overrrided. Hence one way which i prefer is to create an extensions.
public static class Extensions
{
public static bool Equal<T>(this List<T> x, List<T> y)
{
bool isEqual = true;
if (x == null ^ y == null)
{
isEqual = false;
}
else if (x == null && y == null)
{
isEqual = true;
}
else if (x.Equals(y))
{
isEqual = true;
}
else if (x.Count != y.Count)
{
isEqual = false;
}
else
{
//This logic can be changed as per your need.
//Here order of the list matters!
//You can make one where order doesn't matter
for (int i = 0; i < x.Count; i++)
{
if (!x[i].Equals(y[i]))
{
break;
}
}
}
return isEqual;
}
}
Upvotes: 1
Reputation: 318
Doing so you are comparing references but not objects. So you get inequality returned.
Upvotes: 0