.net框架通用物件操作

iDotNetSpace發表於2008-09-16
一.物件的等值性和惟一性

 System.Object型別提供了一個Equals的虛方法,其目的為判斷兩個物件是否有個相同的"值".

.net框架通用物件操作
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt 1 class Object
 2     {
 3         public virtual Boolean Equals(Object obj)
 4         {
 5             //如果兩個引用指向的是同一個物件
 6             //它們肯定相等
 7             if(this==obj)
 8             {
 9                 return (true);
10             }
11 
12             return (false);
13  
14         }
15     }

 

這也許是最簡單的方法.

但有時間,它提供的預設實現對我們來說是不夠的,必須重寫Equals方法.

自己寫的時候,要遵循以下4條規則:

1.Equals方法必須是自反的.也就是說,x.Equals(x)必須返回true.

2.   Equals方法必須是對稱的.也就是說,x.Equals(y)和y.Equals(x)必須返回同樣的值.

3.Equals方法必須是可傳遞的.也就是說,如果x.Equals(y)和y.Equals(z)都返回true,那麼x.Equals(z)也必須返回     true.

4. Equals方法必須是前後一致的.也就是說,如果兩個物件的值沒有發生變化,多次呼叫Equals方法的返回值應該相同.

(一)為基類沒有重寫Object.Equals方法的引用型別實現Equals

 

.net框架通用物件操作
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt  class MyRefType:BaseType
    {
        RefType refobj;   
//引用型別
        ValueType valobj;  //值型別

        
public override bool Equals(object obj)
        {
            
//因為‘this’不為null,所以如果obj為null
            
//那麼兩個物件將不可能相等

            
if (obj == null)
                
return false;

            
//如果兩個物件的型別不同,那麼它們不可能相等
            if (this.GetType() != obj.GetType())
                
return false;
            
//將obj轉型為定義的型別以訪問其中的欄位,這裡的
            
//轉型不會失敗,因為已經知道兩個物件是同一型別

            MyRefType other
=(MyRefType)obj;

            
//比較其中的引用型別欄位
            if (!Object.Equals(refobj, other.refobj))
                
return false;

            
//比較其中的值型別欄位
            if (!valobj.Equals(other.valobj))
                
return false;

            
return true;  //到這裡兩個物件才相等
        }
    }

 

這要注意的:

1.要比較引用型別的欄位,我們應該呼叫Object的靜態方法Equals方法.

    Objext的靜態方法Equals方法是一個比較兩個引用型別物件的輔助方法.採用這種方法比較,是因為即使兩個欄位出現了值為null的情況,程式碼仍會正常執行.

2.要比較值型別的欄位,應該呼叫該欄位型別的Equals方法.不應該呼叫Object的靜態方法Equals方法.因為值型別物件的值永遠不可能為null,並且呼叫Object的靜態方法Equals會對值型別物件執行裝箱操作.

(二)為基類重寫了Object.Equals方法的引用型別實現Equals

 

.net框架通用物件操作
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtclass MyRefType:BaseType
    {
        RefType refobj;   
//引用型別
        ValueType valobj;  //值型別

        
public override bool Equals(object obj)
        {
            
//首先讓基型別比較其中的欄位
            if (!base.Equals(obj))
                
return false;

            
//因為‘this’不為null,所以如果obj為null
            
//那麼兩個物件將不可能相等

            
if (obj == null)
                
return false;

            
//如果兩個物件的型別不同,那麼它們不可能相等
            if (this.GetType() != obj.GetType())
                
return false;
            
//將obj轉型為定義的型別以訪問其中的欄位,這裡的
            
//轉型不會失敗,因為已經知道兩個物件是同一型別

            MyRefType other
=(MyRefType)obj;

            
//比較其中的引用型別欄位
            if (!Object.Equals(refobj, other.refobj))
                
return false;

            
//比較其中的值型別欄位
            if (!valobj.Equals(other.valobj))
                
return false;

            
return true;  //到這裡兩個物件才相等
        }
    }

 

如果呼叫base.Equals會導致呼叫Object.Equals方法,那麼就不應該再呼叫它.這一點很重要.因為只有在兩個引用指向同一個物件時,Object.Equals方法才會返回true.如果兩個引用沒有指向同一個物件,那麼它將返回false.這樣我們實現的Equals方法將總是返回false.

 當然,如果我們定義的型別直接繼承自Object,我們就應該象第一段程式碼那樣來實現Equals.如果我們定義的型別不是直接繼承自Object,我們必須首先確定該型別的基型別是否重寫了Equals方法.如果其中任何一個基型別重寫了Equals方法,那麼我們就應該象這段程式碼先base.Equals方法.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-448573/,如需轉載,請註明出處,否則將追究法律責任。

相關文章