当我使用词典时,有时我必须更改默认的等同含义才能比较键.我看到,如果我重写关键字类上的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 exception d.Add(c,"X"); // d.Add(another,"X"); // same key exception
请注意,我没有必要在两个类中都覆盖Equals,GetHashCode.我可以在实现ICustom的任何对象中使用此比较器,而无需重写比较逻辑.我也可以为“父类”创建IEqualityComparer,并在继承的类上使用.我可以让比较者以不同的方式表现,我可以让一个比较Value而不是Key.
所以IEqualityComparer允许更多的灵活性,你可以实现通用的解决方案.