据我所知,只有在需要值相等语义时才需要覆盖它们。System.Object实现并不“糟糕”,它只执行引用检查(这是该级别上的实现可以执行的所有操作)。
简而言之:如果您需要某种基于值的相等性(基于类属性的相等性),那么是的,可以覆盖它们。否则,已经足够好了。
编辑:
只有在上述情况下才需要覆盖它们。如果您覆盖其中一个,则由于明显的原因(它们需要一致等等),您需要同时覆盖两者。您可以出于其他答案中指出的其他原因(例如使用哈希值的算法(例如Dictionary键)的性能等)在每个类上覆盖它们,但不需要这样做,默认的System.Object实现将正常工作。
编辑2:
请求更多信息,请参考以下伪类:
public class User {
private int _id;
private string _username;
public string Username { get {return _username;}};
public User(string username) {
}
}
当前的代码看起来很直观:
User foo = new User("me");
User bar = new User("me");
User baz = foo;
if (foo.Equals(bar)) {
Console.WriteLine("1: Success!");
}
if (foo.Equals(baz)) {
Console.WriteLine("2: Success!");
}
但是它只会打印出:
2:成功
为什么?foo
和bar
是该类的两个独立实例,并具有单独的引用。引用类似于C/C++中的指针。foo和baz是相同的引用,因为一个是从另一个分配的。它们所有的值都相同,即用户称之为“me”。一个基于值的.Equals
实现的示例可能是:
partial class User {
public override bool Equals(object b) {
if (b == null) return false;
if (b.GetType() != this.GetType()) return false;
User other = (User)b;
if (other._id == this._id) return true;
else return false;
}
}
看到它如何检查类的一部分属性以确定相等性了吗?这就是值相等在起作用。引用相等只需简单的this == b
检查。