<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [你必須知道的.NET]第九回:品味類型---值類型與引用類型(中)-規則無邊

       發布日期:2007.5.28 作者:Anytao

      ?2007 Anytao.com ,原創作品,轉貼請注明作者和出處。

       

      接上回[第八回:品味類型---值類型與引用類型(上)-內存有理]的探討,繼續我們關注值類型和引用類型的話題。

      本文將介紹以下內容:

      • 類型的基本概念 
      • 值類型深入
      • 引用類型深入
      • 值類型與引用類型的比較及應用

        

      1. 引言

      上回[第八回:品味類型---值類型與引用類型(上)-內存有理]的發布,受到大家的不少關注,我們從內存的角度了解了值類型和引用類型的所以然,留下的任務當然是如何應用類型的不同特點在系統設計、性能優化等方面發揮其作用。因此,本回是對上回有力的補充,同時應朋友的希望,我們盡力從內存調試的角度來著眼一些設計的分析,這樣就有助于對這一主題進行透徹和全面的理解,當然這也是下一回的重點。

      從內存角度來討論值類型和引用類型是有理有據的,  而從規則的角度來了解值類型和引用類型是無邊無際的。本文旨在從上文呼應的角度,來把這個主題徹底的融會貫通,無邊無跡的應用,還是來自反復無常的實踐,因此對應用我只能說以一個角度來闡釋觀點,但是肯定不可能力求全局。因此,我們從以下幾個角度來完成對值類型與引用類型應用領域的討論。 

      2. 通用規則與比較

      通用有規則:

      • string類型是個特殊的引用類型,它繼承自System.Object肯定是個引用類型,但是在應用表現上又凸現出值類型的特點,那么究竟是什么原因呢?例如有如下的一段執行:

       

       簡單的說是由于string的immutable特性,因此每次對string的改變都會在托管堆中產生一個新的string變量,上述string作為參數傳遞時,實際上執行了s=s操作,在托管堆中會產生一個新的空間,并執行數據拷貝,所以才有了類似于按值傳遞的結果。但是根據我們的內存分析可知,string在本質上還是一個引用類型,在參數傳遞時發生的還是按址傳遞,不過由于其特殊的恒定特性,在函數內部新建了一個string對象并完成初始化,但是函數外部取不到這個變化的結果,因此對外表現的特性就類似于按值傳遞。至于string類型的特殊性解釋,我推薦Artech的大作《深入理解string和如何高效地使用string》。

      另外,string類型重載了==操作符,在類型比較是比較的是實際的字符串,而不是引用地址,因此有以下的執行結果:

                  string aString = "123";
                  
      string bString = "123";
                  Console.WriteLine((aString 
      == bString)); //顯示為true,等價于aString.Equals(bString);
                  string cString = bString;
                  cString 
      = "456";
                  Console.WriteLine((bString 
      == cString)); //顯示為false,等價于bString.Equals(cString);
      • 通常可以使用Type.IsValueType來判斷一個變量的類型是否為值類型,典型的操作為: 
          public struct MyStructTester
          { }

          
      public class isValueType_Test
          {
              
      public static void Main()
              {
                  MyStructTester aStruct 
      = new MyStructTester();
                  Type type 
      = aStruct.GetType();
                  
      if (type.IsValueType)
                  {
                      Console.WriteLine(
      "{0} belongs to value type.", aStruct.ToString());
                  }
       
              }
          }
      • .NET中以操作符ref和out來標識值類型按引用類型方式傳遞,其中區別是:ref在參數傳遞之前必須初始化;而out則在傳遞前不必初始化,且在傳遞時必須顯式賦值。
      • 值類型與引用類型之間的轉換過程稱為裝箱與拆箱,這值得我們以專門的篇幅來討論,因此留待后文詳細討論這一主題。
      • sizeof()運算符用于獲取值類型的大小,但是不適用于引用類型。
      • 值類型使用new操作符完成初始化,例如:MyStruct aTest = new MyStruct(); 而單純的定義沒有完成初始化動作,此時對成員的引用將不能通過編譯,例如: 
      MyStruct aTest;
      Console.WriteLine(aTest.X); 
      • 引用類型在性能上欠于值類型主要是因為以下幾個方面:引用類型變量要分配于托管堆上;內存釋放則由GC完成,造成一定的CG堆壓力;同時必須完成對其附加成員的內存分配過程;以及對象訪問問題。因此,.NET系統不能由純粹的引用類型來統治,性能和空間更加優越和易于管理的值類型有其一席之地,這樣我們就不會因為一個簡單的byte類型而進行復雜的內存分配和釋放工作。Richter就稱值類型為“輕量級”類型,簡直恰如其分,處理數據較小的情況時,應該優先考慮值類型。
      • 值類型都繼承自System.ValueType,而System.ValueType又繼承自System.Object,其主要區別是ValueType重寫了Equals方法,實現對值類型按照實例值比較而不是引用地址來比較,具體為:
      char a = 'c';
      char b = 'c';
      Console.WriteLine((a.Equals(b))); 
      //會返回true; 
      • 基元類型,是指編譯器直接支持的類型,其概念其實是針對具體編程語言而言的,例如C#或者VB.NET,通常對應用.NET Framework定義的內置值類型。這是概念上的界限,不可混淆。例如:int對應于System.Int32,float對應于System.Single。

      比較出真知:

      • 值類型繼承自ValueType(注意:而System.ValueType又繼承自System.Object);而引用類型繼承自System.Object。
      • 值類型變量包含其實例數據,每個變量保存了其本身的數據拷貝(副本),因此在默認情況下,值類型的參數傳遞不會影響參數本身;而引用類型變量保存了其數據的引用地址,因此以引用方式進行參數傳遞時會影響到參數本身,因為兩個變量會引用了內存中的同一塊地址。
      • 值類型有兩種表示:裝箱與拆箱;引用類型只有裝箱一種形式。我會在下節以專門的篇幅來深入討論這個話題。
      • 典型的值類型為:struct,enum以及大量的內置值類型;而能稱為類的都可以說是引用類型。 struct和class主要的區別可以參見我的拙作《第四回:后來居上:class和struct》來詳細了解,也是對值類型和引用類型在應用方面的有力補充。
      • 值類型的內存不由GC(垃圾回收,Gabage Collection)控制,作用域結束時,值類型會自行釋放,減少了托管堆的壓力,因此具有性能上的優勢。例如,通常struct比class更高效;而引用類型的內存回收,由GC來完成,微軟甚至建議用戶最好不要自行釋放內存。
      • 值類型是密封的(sealed),因此值類型不能作為其他任何類型的基類,但是可以單繼承或者多繼承接口;而引用類型一般都有繼承性。 
      • 值類型不具有多態性;而引用類型有多態性。
      • 值類型變量不可為null值,值類型都會自行初始化為0值;而引用類型變量默認情況下,創建為null值,表示沒有指向任何托管堆的引用地址。對值為null的引用類型的任何操作,都會拋出NullReferenceException異常。
      • 值類型有兩種狀態:裝箱和未裝箱,運行庫提供了所有值類型的已裝箱形式;而引用類型通常只有一種形式:裝箱。

      3. 對癥下藥-應用場合與注意事項

      現在,在內存機制了解和通用規則熟悉的基礎上,我們就可以很好的總結出值類型和引用類型在系統設計時,如何作出選擇?當然我們的重點是告訴你,如何去選擇使用值類型,因為引用類型才是.NET的主體,不必花太多的關照就可以贏得市場。

      3.1 值類型的應用場合

      • MSDN中建議以類型的大小作為選擇值類型或者引用類型的決定性因素。數據較小的場合,最好考慮以值類型來實現可以改善系統性能;
      • 結構簡單,不必多態的情況下,值類型是較好的選擇;
      • 類型的性質不表現出行為時,不必以類來實現,那么用以存儲數據為主要目的的情況下,值類型是優先的選擇;
      • 參數傳遞時,值類型默認情況下傳遞的是實例數據,而不是內存地址,因此數據傳遞情況下的選擇,取決于函數內部的實現邏輯。值類型可以有高效的內存支持,并且在不暴露內部結構的情況下返回實例數據的副本,從安全性上可以考慮值類型,但是過多的值傳遞也會損傷性能的優化,應適當選擇;
      • 值類型沒有繼承性,如果類型的選擇沒有子類繼承的必要,優先考慮值類型;
      • 在可能會引起裝箱與拆箱操作的集合或者隊列中,值類型不是很好的選擇,因為會引起對值類型的裝箱操作,導致額外內存的分配,例如在Hashtable。關于這點我將在后續的主題中重點討論。 

      3.2 引用類型的應用場合

      • 可以簡單的說,引用類型是.NET世界的全值殺手,我們可以說.NET世界就是由類構成的,類是面向對象的基本概念,也是程序框架的基本要素,因此靈活的數據封裝特性使得引用類型成為主流;
      • 引用類型適用于結構復雜,有繼承、有多態,突出行為的場合;
      • 參數傳遞情況也是考慮的必要因素;    

      4. 再論類型判等

      類型的比較通常有Equals()、ReferenceEquals()和==/!=三種常見的方法,其中核心的方法是Equals。我們知道Equals是System.Object提供的虛方法,用于比較兩個對象是否指向相同的引用地址,.NET Framework的很多類型都實現了對Equals方法的重寫,例如值類型的“始祖”System.ValueType就重載了Equal方法,以實現對實例數據的判等。因此,類型的判等也要從重寫或者重載Equals等不同的情況具體分析,對值類型和引用類型判等,這三個方法各有區別,應多加注意。

      4.1 值類型判等

      • Equals,System.ValueType重載了System.Object的Equals方法,用于實現對實例數據的判等。
      • ReferenceEquals,對值類型應用ReferenceEquals將永遠返回false。
      • ==,未重載的==的值類型,將比較兩個值是否“按位”相等。

      4.2 引用類型判等 

      • Equals,主要有兩種方法,如下  
      public virtual bool Equals(object obj);
      public static bool Equals(object objA, object objB);

       一種是虛方法,默認為引用地址比較;而靜態方法,如果objA是與objB相同的實例,或者如果兩者均為空引用,或者如果objA.Equals(objB)返回true,則為true;否則為false。.NET的大部分類都重寫了Equals方法,因此判等的返回值要根據具體的重寫情況決定。 

      • ReferenceEquals,靜態方法,只能用于引用類型,用于比較兩個實例對象是否指向同一引用地址。
      • ==,默認為引用地址比較,通常進行實現了==的重載,未重載==的引用類型將比較兩個對象是否引用地址,等同于引用類型的Equals方法。因此,很多的.NET類實現了對==操作符的重載,例如System.String的==操作符就是比較兩個字符串是否相同。而==和equals方法的主要區別,在于多態表現上,==是被重載,而Equals是重寫。

      有必要在自定義的類型中,實現對Equals和==的重寫或者重載,以提高性能和針對性分析。 

      5. 再論類型轉換

      類型轉換是引起系統異常一個重要的因素之一,因此在有必要在這個主題里做以簡單的總結,我們不力求照顧全面,但是追去提綱挈領。常見的類型轉換包括:

      • 隱式轉換:由低級類型項高級類型的轉換過程。主要包括:值類型的隱式轉換,主要是數值類型等基本類型的隱式轉換;引用類型的隱式轉換,主要是派生類向基類的轉換;值類型和引用類型的隱士轉換,主要指裝箱和拆箱轉換。
      • 顯示轉換:也叫強制類型轉換。但是轉換過程不能保證數據的完整性,可能引起一定的精度損失或者引起不可知的異常發生。轉換的格式為, 
      (type)(變量、表達式)

      例如:int a = (int)(b + 2.02);

      • 值類型與引用類型的裝箱與拆箱是.NET中最重要的類型轉換,不恰當的轉換操作會引起性能的極大損耗,因此我們將以專門的主題來討論。
      • 以is和as操作符進行類型的安全轉換,詳見本人拙作《第一回:恩怨情仇:is和as》。
      • System.Convert類定義了完成基本類型轉換的便捷實現。
      • 除了string以外的其他類型都有Parse方法,用于將字符串類型轉換為對應的基本類型;
      • 使用explicit或者implicit進行用戶自定義類型轉換,主要給用戶提高自定義的類型轉換實現方式,以實現更有目的的轉換操作,轉換格式為,
      static 訪問修飾操作符 轉換修飾操作符 operator 類型(參數列表);

       例如:

      public Student
      {
          
      //
          
          
      static public explicite opertator Student(string name, int age)
          {
              
      return new Student(name, age);
          }

          
      //
      }

      其中,所有的轉換都必須是static的。  

      6. 結論

      現在,我們從幾個角度延伸了上回對值類型和引用類型的分析,正如本文開頭所言,對類型的把握還有很多可以挖掘的要點,但是以偏求全的辦法我認為還是可取的,尤其是在技術探求的過程中,力求面面俱到的做法并不是好事。以上的幾個角度,我認為是對值類型和引用類型把握的必經之路,否則在實際的系統開發中常常會在細小的地方栽跟頭,摸不著頭腦。

      品味類型,我們以應用為要點撬開值類型和引用類型的規矩與方圓。

      品味類型,我們將以示例為導航,開動一個層面的深入分析,下回《第十回:品味類型---值類型與引用類型(下)-應用征途》我們再見。

        

      參考文獻

      (USA)Jeffrey Richter, Applied Microsoft .NET Framework Programming

      (USA)David Chappell, Understanding .NET

        

      溫故知新

      [開篇有益]

      [第一回:恩怨情仇:is和as]

      [第二回:對抽象編程:接口和抽象類]

      [第三回:歷史糾葛:特性和屬性]

      [第四回:后來居上:class和struct]

      [第五回:深入淺出關鍵字---把new說透]

      [第六回:深入淺出關鍵字---base和this]

      [第七回:品味類型---從通用類型系統開始]

      [第八回:品味類型---值類型與引用類型(上)-內存有理]

      ?2007 Anytao.com

      原創作品,轉貼請注明作者和出處,留此信息。

      本貼子以現狀提供且沒有任何擔保,同時也沒有授予任何權利。
      This posting is provided "AS IS" with no warranties, and confers no rights.

      posted @ 2007-05-28 23:13  Anytao  閱讀(17564)  評論(58)    收藏  舉報
      主站蜘蛛池模板: 亚洲国产精品综合久久20| 国产一卡2卡三卡4卡免费网站| 麻豆蜜桃av蜜臀av色欲av| 日韩区一区二区三区视频| 精品国产福利久久久| 国内精品自线在拍| 国产精品自在自线免费观看| 国产精品成人综合色在线| 少妇高潮太爽了在线视频| 亚洲色大成网站WWW久久| 国模精品视频一区二区三区| 亚洲精品国偷自产在线| 日韩欧美在线综合网另类| 熟女精品视频一区二区三区| 风流少妇树林打野战视频| 沛县| 亚洲自拍偷拍中文字幕色| 67194熟妇在线观看线路| 一二三四区无产乱码1000集 | 大地资源高清免费观看| 精品国产迷系列在线观看| 男女吃奶做爰猛烈紧视频| 国产成人综合亚洲第一区| 韩国免费a级毛片久久| 久久99九九精品久久久久蜜桃| 在线无码免费的毛片视频| 国产一区国产二区在线视频| 亚洲成在人线AⅤ中文字幕| 欧洲精品色在线观看| 日韩美av一区二区三区| 亚洲激情一区二区三区在线| 少妇高潮水多太爽了动态图| 精品人妻伦一二三区久久| 香港日本三级亚洲三级| 1024你懂的国产精品| 亚洲精品午夜国产VA久久成人| 亚洲精品香蕉一区二区| 无码av岛国片在线播放| 成人3D动漫一区二区三区| 盐源县| 欧美亚洲另类制服卡通动漫 |