程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#系列之值類型和引用類型

C#系列之值類型和引用類型

編輯:C#入門知識

前言         這幾天一直在思考這章討論什麼, 在上一章討論string的時候牽涉到引用類型,那麼我們這一章討論討論一下,值類型和引用類型。         值類型和引用類型,它們的區別來源於傳值方式。有人會認為值類型就存在棧上這是不一定的。詳細看下文。         有些人會說啊。。有垃圾回收機制進行清理內存。。不需要去折騰那麼多吧 - -!。。。。。為了寫好代碼,避免面試問到。。還是勉為其難的討論討論吧。。。。。   值類型和棧        棧,存儲不是對象成員的值數據類型,還存放著局部變量,參數。        那麼他的工作原理是怎樣的呢?首先要知道,數據在棧上,是從高內存位置往低內存位置填充的,變量地址不會重復的。            假如有下面一段代碼:                  從上面可以看見,b代碼塊是嵌套a代碼塊裡。由於代碼從上到下的執行順序,那麼變量a會比變量b先入棧;可是b代碼塊會比a代碼早結束,超出作用域之後,變量就會釋放,因此,變量b會比變量a先釋放。            由此可見,靈活性並不高,如果希望生命活得長久點?這個時候,堆的作用就體現出來。     引用類型和堆        堆,它的特性和棧有點相反,存儲的是對象成員類型,是從低內存位置往高內存位置填充的。當值類型的變量為類型成員的時候,是與對象存放在堆裡。        先說下工作原理,有這樣一段代碼。   復制代碼 class Program {     static void Main(string[] args)     {         Human h;         h = new Human();     } } 復制代碼          首先,會在棧上分配一個空間,存放引用h,它僅僅是一個引用,不是對象。到第二句進行實例化對象,new 運算符是用來請求分配儲存空間的,CLR會搜索堆上足夠的位置,分配給對象,然後new會返回它所在堆上的地址給引用。因此在棧上存放著該引用指向堆上的對象的地址。   綜上所述:        值類型的使用減少了堆的壓力,同時減少垃圾回收的次數。引用類型卻彌補了生命周期的不足,增加了靈活性。         值類型創建變量時是賦予默認值的,例如int默認值是0。而引用類型創建變量,默認是null。那麼,沒有對象的引用類型的變量使用時會報異常NullReferenceException。        值類型的變量是以復制的方式賦值,執行一次逐字段的復制,而引用類型將對象在堆上的地址賦於新變量進行引用。         下面有段代碼充分說明了引用類型和值類型的區別 :(借用Clr C#的例子)   復制代碼 struct Struct//值類型 {     public int x; }   class Class //引用類型 {     public int x; }   class Program {     static void Main(string[] args)     {         //代碼A         Struct s1 = new Struct();  //分配在棧上          Class c1 = new Class();    //分配在堆上          s1.x = 1;         c1.x = 1;           Console.WriteLine(s1.x);  //輸出1          Console.WriteLine(c1.x);  //輸出1           //代碼B         Struct s2 = s1;           //復制棧上成員給s2         Class c2 = c1;            //復制引用給c2         s2.x = 2;                 //值類型,s1.x不變,s2.x 變更          c2.x = 2;                 //引用類型,c1.x和c2.x 同時改變            Console.WriteLine(s1.x);  //1 值類型          Console.WriteLine(s2.x);  //2 值類型            Console.WriteLine(c1.x);  //2 引用類型          Console.WriteLine(c2.x);  //2 引用類型     } } 復制代碼   c1將地址復制給c2,也就是說c1和c2指向的是同一個對象,因此c1和c2其中一個修改了,另外的也會受影響。     s1將成員復制給s2,雖然s1和s2存儲了相同的值,但是他們內存地址都不相同,存的是屬於自己的值,因此s1和s2其實一個修改了,也不會影響另外一個。   結尾       寫到這裡也差不多了。其實說到引用類型和值類型,還說牽涉到裝箱和拆箱的,小弟對那塊還沒多深的了解,等以後再和大家探討。   感冒了。。休息去。。。一個多星期還沒好,今天貌似又嚴重了。。公司的流感太厲害了。。希望各位注意身體。。=。=。。。。。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved