經過前面三篇關於.NET Framework源碼研究系列的隨筆,相信大家都發現其實.NET Framework的實現其實並不復雜,也許跟我們自己做的項目開發差不多.本人也是這樣的看法.不 過,經過仔細深入的研究,我們還是會發現一下平時很難注意到的東西,而這些東西對我們完善思 路,開闊眼界,鍛煉良好的編碼素質有著很大的意義.
我們知道.NET中所有的類型(包括:引用類型,值類型)都從Object類派生過來,由此可以說 Object是所有類型的根本.那麼今天我們就研究.NET(C#)中一切元素的根本--- System.Object.
Object類在.NET源碼中的實現很簡單,一共不過100行左右的代碼,這也是我們有精力可以仔 細研究它的每一行代碼.先看它的定義.
1 [Serializable()]
2 [ClassInterface(ClassInterfaceType.AutoDual)]
3 [System.Runtime.InteropServices.ComVisible(true)]
4 public class Object
由定義來看,Object好像是一個普通的類(莫非Object也從Object派生而來?! ^_^ ).Serializable標簽說明了Object可以做序列化反序列化操作. ClassInterface (ClassInterfaceType.AutoDual),System.Runtime.InteropServices.ComVisible(true) 是.NET為了支持COM特別設計的.除非你要手動包裝COM,否則對於絕大部分時間都是用托管代碼 而言的人沒什麼意義.
接下來看它的構造函數:
1 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
2 public Object(){ }
3 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
4 ~Object() {}
從上面的代碼看到Object只有一個空方法體的構造函數,這就是宇宙起源一樣,剛開始什麼都 沒有.此處要特別說明的是ReliabilityContract標簽.ReliabilityContract定義某些代碼的作 者和依賴於這些代碼的開發人員之間的可協靠性定。這是官方的定義,聽起來有些玄 乎.ReliabilityContract有兩個屬性,分別是兩個枚舉:Cer和ConsistencyGuarantee.Cer指在受 約束的執行區域內調用時指定方法的行為;ConsistencyGuarantee指可靠性協定。看MSDN對這兩 個枚舉的說明後,我們發現 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]為Object提供了安全性保證,就是說我們在調用Object構造函數時不管有沒有遇 到異常情況,總會獲知執行結果.
另外,Object顯式定義了析構函數(又是一個不推薦的做法,微軟好像很喜歡做的不推薦我們 做的@_@||),讓我們能夠手動釋放對象占用的資源而不需要等到GC自動釋放.
要特別說明的是,這裡有個我們很少遇到的一個概念:CER,即受約束的執行區域 , 是創作可 靠托管代碼的機制的一部分。CER 定義一個區域,在該區域中公共語言運行庫 (CLR) 會受到約 束,不能引發可使區域中的代碼無法完全執行的帶外異常。在該區域中,用戶代碼受到約束, 不能執行會導致引發帶外異常的代碼。
看完構造函數後我們看下Object中最常用的三個方法的實現,代碼如下:
public virtual String ToString(){
return GetType().ToString();
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern Type GetType();
public virtual bool Equals(Object obj){
return InternalEquals(this, obj);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern bool InternalEquals(Object objA, Object objB);
public virtual int GetHashCode(){
return InternalGetHashCode(this);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int InternalGetHashCode(Object obj);
感覺有的悲劇,因為這三個方法什麼都沒做,直接調用了CLR的內部方法,看來Object也是個馬 甲:( .微軟官方號稱Object類是所有類的基類在此恐怕要打個問號.我猜想此Object非彼 Object.說不定CLR中也有一個Object.
如果說上面三個方法有點讓人無語,那麼下面的代碼就更讓人困惑了.
private void FieldSetter(String typeName, String fieldName, Object val){
FieldInfo fldInfo = GetFieldInfo(typeName, fieldName);
if (fldInfo.IsInitOnly)
throw new FieldAccessException(Environment.GetResourceString ("FieldAccess_InitOnly"));
System.Runtime.Remoting.Messaging.Message.CoerceArg(val, fldInfo.FieldType);
fldInfo.SetValue(this, val);
}
private void FieldGetter(String typeName, String fieldName, ref Object val){
FieldInfo fldInfo = GetFieldInfo(typeName, fieldName);
val = fldInfo.GetValue(this);
}
private FieldInfo GetFieldInfo(String typeName, String fieldName) {
Type t = GetType();
while (null != t){
if (t.FullName.Equals(typeName)){
break;
}
t = t.BaseType;
}
if (null == t){
throw new RemotingException(String.Format (CultureInfo.CurrentCulture, Environment.GetResourceString ("Remoting_BadType"),typeName));
}
FieldInfo fldInfo = t.GetField(fieldName, BindingFlags.Public |BindingFlags.Instance |BindingFlags.IgnoreCase);
if (null == fldInfo){
throw new RemotingException(String.Format (CultureInfo.CurrentCulture, Environment.GetResourceString ("Remoting_BadField"),fieldName, typeName));
}
return fldInfo;
}
上面一段代碼似乎讀取或設置一個字段的值(我們也是這樣的做法).問題時,我根本沒有找到 Object中用到這幾個方法的地方,private又決定了擴展類也不可能訪問.那麼這三個方法到底有 什麼用,恐怕只有微軟自己知道了.
小結
經過上面的分析,我們發現Object實現其實很簡單,幾乎沒有內容.但Object中出現的CER給我 們撰寫高安全性代碼帶來一點思考.