问题
I'm trying to make a method that can compare any two lists for equality. I'm trying to compare them in a way that validates that every element of one list has the same value as every element of another list. My Equals
method below always returns false
, can anyone see why that is?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class IEnumerableComparer<T> : IEqualityComparer<IEnumerable<T>>
{
public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
{
for(int i = 0; i<x.Count();i++){
if(!Object.Equals(x.ElementAt(i), y.ElementAt(i))){
return false;
}
}
return true;
}
public int GetHashCode(IEnumerable<T> obj)
{
if (obj == null)
return 0;
return unchecked(obj
.Select(e => e.GetHashCode())
.Aggregate(0, (a, b) => a + b));
}
}
Here is my data I'm using to test this Equals
method:
static void Main(string[] args)
{
Car car1 = new Car();
car1.make = "Toyota";
car1.model = "xB";
Car car2 = new Car();
car2.make = "Toyota";
car2.model = "xB";
List<Car> l1 = new List<Car>();
List<Car> l2 = new List<Car>();
l1.Add(car1);
l2.Add(car2);
IEnumerableComparer<Car> seq = new IEnumerableComparer<Car>();
bool b = seq.Equals(l1, l2);
Console.Write(b); //always says false
Console.Read();
}
}
Car class:
class Car
{
public String make { get; set; }
public String model { get; set; }
}
回答1:
The default version of Equals compares references (for reference types). There are three possible solutions to your problem:
override
Equals
andGetHashCode
for theCar
classadd another version of
IEnumerableComparer<T>
constructor accepting IEqualityComparer<T> which will be used to compare individual instances and provide its implementation for each use caseuse only value types, as for them the default version of Equals will behave as you expect. Note that all fields and properties of these value types will have to conform to the 1st or 3rd option given here (i.e. either have
Equals
andGetHashCode
overridden or be a value type also). It's not really a recommended solution in general, I just mention it as a theoretical possibility. In your case it would help though - try changingclass Car
tostruct Car
.
Also, as correctly pointed out by wageoghe's answer you can use the SequenceEqual method instead of writing your own implementation, but still you need to comply to one of the solutions given above (using this SequenceEqual overload for the second option).
回答2:
Maybe I'm missing something, but why not use SequenceEqual?
http://msdn.microsoft.com/en-us/library/bb348567(v=vs.110).aspx
Bool b = l1.SequenceEqual(l2);
Note that the objects in the sequences still must implement Equals and GetHashCode correctly.
回答3:
Give your car the overrides as well:
class Car
{
public String make { get; set; }
public String model { get; set; }
public override bool Equals(object obj)
{
var other = obj as Car;
return (other != null)
&& (this.make == other.make)
&& (this.model == other.model);
}
public override int GetHashCode()
{
return make.GetHashCode() ^ model.GetHashCode();
}
}
来源:https://stackoverflow.com/questions/19883357/trying-to-implement-a-method-that-can-compare-any-two-lists-but-it-always-return