《C#编程指南》中的重载Equals()和操作符==的指导方针部分表示:
不建议在非不可变类型中重写操作符==。
较新的.NET Framework 4文档实现Equals和相等运算符(==)的指导方针省略了该声明,尽管社区内容中的一篇帖子重复了这一说法并引用了旧文档。
似乎至少对于一些简单的可变类(例如),重写Equals()是合理的。
public class ImaginaryNumber
{
public double RealPart { get; set; }
public double ImaginaryPart { get; set; }
}
在数学中,两个虚数具有相同的实部和虚部时,在测试等式的时间点上它们实际上是相等的。如果使用具有相同RealPart和ImaginaryPart的单独对象进行Equals()未被覆盖,则断言它们“不相等”是不正确的。
另一方面,如果重写了Equals(),则也应该重写GetHashCode()。如果一个重写了Equals()和GetHashCode()的虚数被放置在HashSet中,并且可变实例改变了其值,那么这个对象将不再被找到。
MSDN是否有错误地删除了关于不覆盖非不变类型的Equals()和operator==的指南?
对于“在现实世界”中所有属性的等价性意味着对象本身相等的可变类型(例如ImaginaryNumber),覆盖Equals()是否合理?
如果是合理的,如何在对象实例参与依赖于GetHashCode()不改变的HashSet或其他内容时处理潜在的可变性?
更新
我刚在MSDN上看到了这个内容
通常,当预期将该类型的对象添加到某种集合中或其主要目的是存储一组字段或属性时,您会实现值相等性。您可以基于类型中的所有字段和属性进行值相等性的定义,也可以基于子集进行定义。但无论哪种情况,在类和结构体中,您的实现都应遵循等价性的五个保证:
ImaginaryNumber
作为一个可变类型是不合理的。 - Damien_The_Unbelieverint
、long
、double
等是不可变的(immutable)。一个5
就是一个5
,无法改变它的本质。 - Odedi
的值已经改变,但Int32
类型的0
仍然是0
。 - dlev