.NET Framework源碼研究系列之---萬法歸宗Object

作者: 倪大蝦  來源: 博客園  發布時間: 2010-08-01 13:39  閱讀: 1527 次  推薦: 0   原文鏈接   [收藏]  

  經過前面三篇關于.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給我們撰寫高安全性代碼帶來一點思考。

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()