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不會爲新對象調用構造器,而只是保證它的狀態和原對象一致。