首頁  >  文章  >  後端開發  >  C#中值類型與引用類型的詳細介紹

C#中值類型與引用類型的詳細介紹

黄舟
黄舟原創
2017-10-01 07:24:471162瀏覽

這篇文章主要為大家詳細介紹了C#中值類型和引用類型的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下

在C#中,值類型和引用型別是相當重要的兩個概念,必須在設計型別的時候就決定型別實例的行為。如果在編寫程式碼時無法理解引用類型和值類型的區別,那麼將會為程式碼帶來不必要的異常。很多人就是因為沒有弄清楚這兩個概念從而在程式設計過程中遇到了很多問題,在這裡部落客淺談對值類型和引用類型的認識。

首先從概念上看,值類型直接儲存其值,而引用類型儲存對其值的引用。從而這兩種類型儲存在記憶體的不同地方。

其次從記憶體空間上看,值類型是在堆疊中操作,而參考類型則在堆中分配儲存單元。

堆疊在編譯的時候就分配好記憶體空間,在程式碼中有堆疊的明確定義,而堆是程式運作中動態分配的記憶體空間,可以根據程式的運作動態地分配記憶體的大小。因此,值類型總是在記憶體中佔用一個預先定義的位元組數。而引用型別的變數則在堆疊中分配一個記憶體空間,這個記憶體空間包含的是對另一個記憶體位置的引用,這個位置是託管堆中的一個位址,也就是存放此變數實際值的地方。

也就是說值類型相當於現金,要用就直接用,而引型別相當於存摺,要用得先去銀行取。

但值類型在堆疊上分配內存,而引用類型在託管堆上分配內存,只是一種籠統的說法。下面對其進行詳細描述。

(1)對於值類型的實例,如果作為方法中的局部變量,則創建在線程棧上;如果該實例作為類型的成員,則作為類型成員的一部分,連同其他類型字段存放在託管堆上。

每種值型別都有一個隱式的預設建構子來初始化該型別的預設值。例如:


int i = new int();

等價於:


#
Int32 i = new Int32();

等價於:


##

int i = 0;

等價於:


Int32 i = 0;

#使用new運算子時,將呼叫特定類型的預設建構子並對變數賦以預設值。在上例中,預設建構函數將值0賦給了i。

說明:C#的所有值型別均隱含衍生自System.ValueType,而System.ValueType直接衍生於System.Object。即System.ValueType本身是一個類別類型,而不是值型別。其關鍵在於ValueType重寫了Equals方法,從而將值類型依照實例的值來比較,而不是引用位址來比較。

(2)引用類型的實例是建立在託管堆上。

下面以一段程式碼來詳細講解一下值類型與引用類型的區別


#

namespace Test 
  { 
      class Program 
      { 
        static void Main(string[] args) 
        { 
       //调用ReferenceAndValue类中的Demonstration方法 
          ReferenceAndValue.Demonstration(); 
          Console.ReadLine(); 
        } 
      } 
      public class stamp       //定义一个类 
      { 
        public string Name { get; set; }    //定义引用类型 
        public int Age { get; set; }    //定义值类型 
      } 
      public static class ReferenceAndValue   //定义一个静态类 
      { 
        public static void Demonstration()   //定义一个静态方法 
        { 
          stamp Stamp_1 = new stamp { Name = "Premiere", Age = 25 }; //实例化 
          stamp Stamp_2 = new stamp { Name = "Again", Age = 47 }; //实例化 
          int age = Stamp_1.Age;     //获取值类型Age的值 
          Stamp_1.Age = 22;     //修改值类型的值 
          stamp guru = Stamp_2;     //获取Stamp_2中的值 
          Stamp_2.Name = "Again Amend";   //修改引用的Name值 
          Console.WriteLine("Stamp_1's age:{0}", Stamp_1.Age); //显示Stamp_1中的Age值 
          Console.WriteLine("age's value:{0}", age); //显示age值 
          Console.WriteLine("Stamp_2's name:{0}", Stamp_2.Name); //显示Stamp_2中的Name值 
          Console.WriteLine("guru's name:{0}", guru.Name); //显示guru中的Name值 
        } 
    } 
  }

透過執行上面一段程式之後我們可以看出,當改變了Stamp_1.Age的值時,age並沒有跟著變,但在改變了anders.Name的值後,guru.Name卻跟著變了,這就是值型別和引用型別的差別。在聲明age值類型變數時,將Stamp_1.Age的值賦給它,這時,編譯器在堆疊上分配了一塊空間,然後把Stamp_1.Age的值填進去,二者沒有任何關聯,就像在計算機中複製檔案一樣,只是把Stamp_1.Age的值拷貝給age了。而引用型別則不同,在聲明guru時把Stamp_2賦給它,前面說過,引用型別包含的只是堆上資料區域位址的引用,其實就是把Stamp_2的引用也賦給guru,因此它們指向了同一塊記憶體區域。既然是指向同一塊區域,不管修改誰,另一個的值都會跟著改變,就像信用卡跟親情卡一樣,用親情卡取了錢,與之關聯的信用卡帳上也會跟著改變。

以上是C#中值類型與引用類型的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn