引言
最近一个朋友正在找工作,他说在笔试题中遇到Equals和==有什么区别的题,当时跟他说如果是值类型的,它们没有区别,如果是引用类型的有区别,但string类型除外。为了证实自己的说法,也研究了一下,以免误导别人,这里将研究结果总结一下,如果我有什么地方说的不对的地方,望指出。
相等性
在定义类或结构时,您将决定为类型创建值相等性(或等效性)的自定义定义是否有意义。 通常,当类型的对象预期要添加到某类集合时,或者当这些对象主要用于存储一组字段或属性时,您将实现值相等性。 您可以基于类型中所有字段和属性的比较来定义值相等性,也可以基于子集进行定义。 但在任何一种情况下,类和结构中的实现均应遵循五个等效性保证条件:
1.x.Equals(x) 返回 true. 。这称为自反属性。
2.x.Equals(y) 返回与 Equals(x) 相同的值。 这称为对称属性。
3.如果 (x.Equals(y) && y.Equals(z)) 返回 true,则 x.Equals(z) 返回 true。 这称为可传递属性。
4.只要不修改 x 和 y 所引用的对象,x.Equals(y) 的后续调用就返回相同的值。
5.x.Equals(null) 返回 false。 但是,null.Equals(null) 会引发异常;它不遵循上面的第二条规则。
您定义的任何结构已经具有它从 Object.Equals(Object) 方法的 System.ValueType 重写中继承的默认值相等性实现。 此实现使用反射来检查类型中的所有公共和非公共字段以及属性。 尽管此实现可生成正确的结果,但与您专门为类型编写的自定义实现相比,它的速度相对较慢。
类和结构的值相等性的实现详细信息不同。 但是,类和结构都需要相同的基础步骤来实现相等性:
重写 Object.Equals(Object)虚方法。 大多数情况下,您的 bool Equals( object obj ) 实现应只调入作为 System.IEquatable<T> 接口的实现的类型特定 Equals 方法。 (请参见步骤 2。)
通过提供类型特定的 Equals 方法实现 System.IEquatable<T> 接口。 实际的等效性比较将在此接口中执行。 例如,您可能决定通过仅比较类型中的一两个字段来定义相等性。 不要从 Equals 中引发异常。 仅适用于类:此方法应仅检查类中声明的字段。 它应调用 base.Equals 来检查基类中的字段。 (如果类型直接从 Object 中继承,则不要这样做,因为 Object.Equals(Object) 的 Object 实现会执行引用相等性检查。)










