使用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();
        }
    }
}

}

两个示例的结果相同.

谢谢.

当您覆盖EqualsGetHashCode时,您正在更改对象确定其是否等于另一个对象的方式.需要注意的是,如果使用==运算符比较对象,除非您也重写了该运算符,否则它不会具有与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

请注意,在这两个类中,我都不必覆盖EqualsGetHashCode.我可以在实现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.