第六章 通用对象操作
Ø 6.1 对象的等值性与唯一性
Equals方法采取的策略:如果进行比较的两个引用指向的是同一个对象,方法将返回true;否则在任何其他情况下,方法都将返回false。
当实现Equals方法时,必须遵循4条规则:
1. Equals方法必须是自反的
2. Equals方法必须是对称的
3. Equals方法必须是可传递的
4. Equals方法必须是前后一致的
Ø 6.1.1 为基类没有重写Object.Equals方法的引用类型实现Equals
1. 比较引用类型的字段 我们应该调用Object的静态Equals方法,这样即使两个字段出现了值为null的情况,代码仍会正常进行。
2. 比较值类型字段 我们应该调用该字段类型的Equals方法来比较他们。我们不需调用Object的静态Equals方法,因为值类型不可能为null,而且Object的静态Equals方法会对值类型执行装箱操作。
Ø 6.1.2 为基类重写了Object.Equals方法的引用类型实现Equals
如果我们定义的类型不是直接继承自Object,我们必须首先确定该类型的基类型是否重写了Equals方法,如果其中任何一个基类型重写了Equals方法,那么我们就应该首先调用base.Equals方法来判断基类型方法是否相等。
Ø 6.1.3 为值类型实现Equals方法
对于值类型,我们应该为它定义一个强类型版本的Equals方法,让其接受定义类型作为参数。这样做不仅可以提供类型安全,而且还可以避免额外的装箱操作。除此之外,我们也应该为==和!=提供强类型的重载操作符。
Ø 6.1.4 Equals方法与==/!=操作符的实现总结
对于自己定义的引用类型,我们应该重写Equals方法,在其内部比较对象的状态,如果我们定义的类型的基类型没有继承Object.Equals方法的实现,那么我们应该调用基类型的Equals方法。如果愿意我们可以重载==和!=操作符,让它们调用重写后的Equals方法。
Ø 6.1.5 对象唯一性识别
如果判断两个引用是否指向同一个对象,可以使用Object.ReferenceEquals静态方法
Ø 6.2 对象的散列码
如果重写了Equals方法,而没有重写GetHashCode方法,编译器会发出一个警告信息。一个类必须同时重写Equals和GetHashCode方法是因为System.Collections.HashTable类型的实现要求任何两个相等的对象都必须有相同的散列码值。如果我们重写了Equals方法,我们也应该重写GetHashCode方法以确保用来判等的算法和用来计算对象散列码的算法一致。
Ø 6.3 对象克隆
如果希望自己的实例被克隆,该类应该实现ICloneable接口
浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。
深拷贝是指对对象实例中字段引用的对象也进行拷贝的一种方式。执行深拷贝后,原来对象和新创建的对象不会共享任何东西,改变一个对象不会对另一个对象有任何影响。
如果希望自己的类型实现浅拷贝,可以调用System.Object的受保护方法MemberwiseClone即可。