C# · 12月 31, 2021

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

当我使用词典时,有时我必须更改默认的等同含义才能比较键.我看到,如果我重写关键字类上的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(); } }}

}

第二个 :

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); DicEqualityComparer dic = new DicEqualityComparer(); Dictionary<Customer,string>(dic); Console.WriteLine(c1.Equals(c2)); try { d.Add(c1,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具有相同的行为,除非你也覆盖运算符.

这样做你改变了一个类的行为,如果你需要与其他类相同的逻辑怎么办?如果您需要“通用比较”.这就是为什么你有IEqualityComparer.

看这个例子(full code on Github)

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; }}

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

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 exceptiond.Add(c,”X”);// d.Add(another,”X”); // same key exception

请注意,我没有必要在两个类中都覆盖Equals,GetHashCode.我可以在实现ICustom的任何对象中使用此比较器,而无需重写比较逻辑.我也可以为“父类”创建IEqualityComparer,并在继承的类上使用.我可以让比较者以不同的方式表现,我可以让一个比较Value而不是Key.

所以IEqualityComparer允许更多的灵活性,你可以实现通用的解决方案.