使用IEqualityComparer和Equals/GethashCode Override有什么区别?

dar*_*624 19 c# equality equals iequalitycomparer gethashcode

当我使用字典有时我必须更改默认的等于意思,以便比较键.我看到如果我在键的类上重写Equals和GetHashCode,或者我创建了一个实现IEqualityComparer的新类,我有相同的结果.那么使用IEqualityComparer和Equals/GethashCode Override有什么区别?两个例子:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

}

第二个 :

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

}

两个例子都有相同的结果.

提前致谢.

Bru*_*oLM 14

当您覆盖Equals并且GetHashCode您正在更改对象将确定它是否等于另一个对象的方式时.还有一个注意事项,如果使用==运算符比较对象,则Equals除非您重写运算符,否则它将具有相同的行为.

这样做就改变了单个类的行为,如果你需要为其他类提供相同的逻辑呢?如果您需要"通用比较".这就是你拥有的原因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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我有两个不同的类,都可以使用相同的比较器.

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
Run Code Online (Sandbox Code Playgroud)

请注意,我没有覆盖Equals,GetHashCode在既没有类.我可以在任何实现的对象中使用此比较器,ICustom而无需重写比较逻辑.我也可以创建IEqualityComparer一个"父类"并使用继承的类.我可以让比较器以不同的方式运行,我可以做一个比较Value而不是Key.

因此,IEqualityComparer允许更多灵活性,您可以实现通用解决方案

  • 简单地说,IEqualityComparer将比较逻辑外部化,同时覆盖Equals/GetHashCode将它们内化 - IComparable(内化)和IComparer(Externalize)的原理/差异相同. (11认同)