1. 通用对象操作
1.1. 对象的等值性与唯一性
System.Object类型中的Equals方法实现:
class Object{
public virtual Boolean Equals(Object obj){
if ( this == obj )
return true;
return false;
}
public static Boolean Equals(Object objA, Object objB){
if ( objA == objB )
return true;
if ( objA == null || objB == null )
return false;
return objA.Equals(objB);
}
}
System.ValueType.Equals方法实现:
class ValueType {
public override Boolean Equals(Object obj){
if ( obj == null )
return false;
Type thisType = this.GetType();
If ( thisType != obj.GetType() )
Return false;
FieldInfo[] fields = thisType.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
for ( Int32 I = 0; I < fields.Length; i++ ){
Object thisValue = fields[i].GetValue(this);
Object thatValue = fields[i].GetValue(obj);
If ( !Object.Equals(thisValue, thatValue) )
Return false;
}
return true;
}
}
1. 为基类没有重写Object.Equals方法的引用类型实现Equals方法
class MyRefType : BaseType{
RefType refobj;
ValType valobj;
public override Boolean Equals(Object obj){
if ( obj == null )
return false;
if ( this.GetType() != obj.GetType() )
return false;
MyRefType other = (MyRefType)obj;
if ( !Object.Equals(refobj, other.refobj) )
return false;
if ( !valobj.Equals(other.valobj) )
return false;
return true;
}
public static Boolean operator==(MyRefType o1, MyRefType o2){
return Object.Equals(o1, o2);
public static Boolean operator!=(MyRefType o1, MyRefType o2){
return !(o1 == o2);
}
2. 为基类重写了Object.Equals方法的引用类型实现Equals方法
class MyRefType : BaseType{
RefType refobj;
ValType valobj;
public override Boolean Equals(Object obj){
if ( !base.Equals(obj) )
return false;
if ( obj == null )
return false;
if ( this.GetType() != obj.GetType() )
return false;
MyRefType other = (MyRefType)obj;
if ( !Object.Equals(refobj, other.refobj) )
return false;
if ( !valobj.Equals(other.valobj) )
return false;
return true;
}
public static Boolean operator==(MyRefType o1, MyRefType o2){
return Object.Equals(o1, o2);
public static Boolean operator!=(MyRefType o1, MyRefType o2){
return !(o1 == o2);
}
如果调用base.Equals会导致调用Object.Equals方法,那么就不应该再调用它。因为Object.Equals方法只有在两个对象指向同一个对象时才会返回true。
如果定义的类型直接继承自Object,应该采用第一种方式。如果定义的类型不是直接继承自Object,首先确定该类型的基类型(除Object之外)是否重新了Equals方法,如果没有任何基类重写Equals方法,则采用第一中方式,否则采用第二种方式。
3. 为值类型实现Equals方法
struct MyValType{
RefType refobj;
ValType valobj;
public override Boolean Equals(Object obj){
If ( !obj is MyValType) )
Return false;
Return this.Equals((MyValType)obj);
}
public override Boolean Equals(MyValType obj){
If ( Object.Equals(this.refobj, obj.refobj) )
Return false;
If ( this.valobj.Equals(obj.valobj) )
Return false;
Return true;
}
public static Boolean operator==( MyValType o1, MyValType o2){
return Object.Equals(o1, o2);
public static Boolean operator!=( MyValType o1, MyValType o2){
return !(o1 == o2);
}
对于值类型应该为它定义一个强类型版本的Equals方法,让其接受定义类型作为参数。但是如果MyValType和别的类型之间定义了隐式转换,它们将有可能被判为相等,而它们的类型却不相同。
在上面接受Object参数的Equals方法中,使用is操作符来检查obj的类型。这里使用is而不使用GetType是因为在值类型实例上调用GetType会导致装箱。而前面引用类型MyRefType的Equals实现,则只能使用GetType方法,而不能使用is操作符。因为is操作符在判断一个对象与它的任何一个基类型之间的关系时都会返回true。
4. 对象唯一性识别
class Object{
public static Boolean ReferenceEquals(Object objA, Object objB){
return (objA == objB);
}
当C#编译器看到使用==操作符来比较两个类型为Object的引用时,编译器会产生比较两个对象引用是否相同的IL代码。
编译时类型又称声明类型、静态类型,是代码中显式声明的类型。运行时类型又称实际类型、动态类型,是变量所引用的对象的真实类型。GetType方法返回的是运行时类型。
1.2. 对象的散列码
一个类型必须同时重写Equals方法和GetHashCode方法,因为System.Collections.Hashtable类型的实现要求任何两个相等的对象都必须有相同的散列码。
1.3. 对象克隆
浅拷贝(shallow copy)是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。而深拷贝(deep copy)是对对象实例中字段引用的对象也进行拷贝的一种方式。
Object.MemberwiseClone方法实现:
1) 为新对象分配内存;
2) 遍历类型中的所有实例字段,并将原对象中所有的位拷贝到新对象中;
MemberwiseClone
不会为新对象调用构造器,而只是保证它的状态和原对象一致。