使用IEqualityComparer和Equals/GethashCode Override有什么区别?
当我使用词典时,有时我必须更改默认的Equals含义才能比较键.我看到,如果我在键的类上重写了Equals和GetHashCode,或者我创建了一个实现IEqualityComparer的新类,则结果相同.那么,使用IEqualityComparer和Equals/GethashCode Override有什么区别? 两个例子:
When i am using dictionaries sometimes I have to change the default Equals meaning in order to compare Keys. I see that if I override the Equals and GetHashCode on the key's class or i create a new class which implements IEqualityComparer I have the same result. So what's the difference between using IEqualityComparer and Equals/GethashCode Override? Two Examples:
class Customer
{
public string name;
public int age;
public Customer(string n, int a)
{
this.age = a;
this.name = n;
}
public override bool Equals(object obj)
{
Customer c = (Customer)obj;
return this.name == c.name && this.age == c.age;
}
public override int GetHashCode()
{
return (this.name + ";" + this.age).GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
Customer c1 = new Customer("MArk", 21);
Customer c2 = new Customer("MArk", 21);
Dictionary<Customer, string> d = new Dictionary<Customer, string>();
Console.WriteLine(c1.Equals(c2));
try
{
d.Add(c1, "Joe");
d.Add(c2, "hil");
foreach (KeyValuePair<Customer, string> k in d)
{
Console.WriteLine(k.Key.name + " ; " + k.Value);
}
}
catch (ArgumentException)
{
Console.WriteLine("Chiave già inserita in precedenza");
}
finally
{
Console.ReadLine();
}
}
}
}
第二个:
class Customer
{
public string name;
public int age;
public Customer(string n, int a)
{
this.age = a;
this.name = n;
}
}
class DicEqualityComparer : EqualityComparer<Customer>
{
public override bool Equals(Customer x, Customer y) // equals dell'equalitycomparer
{
return x.name == y.name && x.age == y.age;
}
public override int GetHashCode(Customer obj)
{
return (obj.name + ";" + obj.age).GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
Customer c1 = new Customer("MArk", 21);
Customer c2 = new Customer("MArk", 21);
DicEqualityComparer dic = new DicEqualityComparer();
Dictionary<Customer, string> d = new Dictionary<Customer, string>(dic);
Console.WriteLine(c1.Equals(c2));
try
{
d.Add(c1, "Joe");
d.Add(c2, "hil");
foreach (KeyValuePair<Customer, string> k in d)
{
Console.WriteLine(k.Key.name + " ; " + k.Value);
}
}
catch (ArgumentException)
{
Console.WriteLine("Chiave già inserita in precedenza");
}
finally
{
Console.ReadLine();
}
}
}
}
两个示例的结果相同.
谢谢.
当您覆盖Equals
和GetHashCode
时,您正在更改对象确定其是否等于另一个对象的方式.需要注意的是,如果使用==
运算符比较对象,除非您也重写了该运算符,否则它不会具有与Equals
相同的行为.
When you override Equals
and GetHashCode
you are changing the way the object will determine if it is equals to another. And a note, if you compare objects using ==
operator it will not have the same behavior as Equals
unless you override the operator as well.
是否更改了单个类的行为,如果其他类需要相同的逻辑怎么办?如果需要通用比较".这就是为什么您拥有IEqualityComparer
.
Doing that you changed the behavior for a single class, what if you need the same logic for other classes? If you need a "generic comparison". That is why you have IEqualityComparer
.
看这个例子:
interface ICustom
{
int Key { get; set; }
}
class Custom : ICustom
{
public int Key { get; set; }
public int Value { get; set; }
}
class Another : ICustom
{
public int Key { get; set; }
}
class DicEqualityComparer : IEqualityComparer<ICustom>
{
public bool Equals(ICustom x, ICustom y)
{
return x.Key == y.Key;
}
public int GetHashCode(ICustom obj)
{
return obj.Key;
}
}
我有两个不同的类,都可以使用同一个比较器.
I have two different classes, both can use the same comparer.
var a = new Custom { Key = 1, Value = 2 };
var b = new Custom { Key = 1, Value = 2 };
var c = new Custom { Key = 2, Value = 2 };
var another = new Another { Key = 2 };
var d = new Dictionary<ICustom, string>(new DicEqualityComparer());
d.Add(a, "X");
// d.Add(b, "X"); // same key exception
d.Add(c, "X");
// d.Add(another, "X"); // same key exception
请注意,在这两个类中,我都不必覆盖Equals
和GetHashCode
.我可以在实现ICustom
的任何对象中使用此比较器,而不必重写比较逻辑.我还可以为父类"创建一个IEqualityComparer
,并在继承的类上使用.我可以有一个比较器,以不同的方式表现,我可以让一个比较器来比较Value
而不是Key
.
Notice that I didn't have to override Equals
, GetHashCode
in neither of the classes. I can use this comparer in any object that implements ICustom
without having to rewrite the comparison logic. I can also make an IEqualityComparer
for a "parent class" and use on classes that inherit. I can have comparer that will behave in a different way, I can make one to compare Value
instead of Key
.
因此IEqualityComparer
提供了更大的灵活性,您可以实施通用解决方案.
So IEqualityComparer
allows more flexibility and you can implement generic solutions.