C#中值類型和引用類型解析
在C#中,值類型和引用類型是相當重要的兩個概念,必須在設計類型的時候就決定類型實例的行為。如果在編寫代碼時不能理解引用類型和值類型的區(qū)別,那么將會給代碼帶來不必要的異常。很多人就是因為沒有弄清楚這兩個概念從而在編程過程中遇到了很多問題,在這里博主淺談對值類型和引用類型的認識。
首先從概念上看,值類型直接存儲其值,而引用類型存儲對其值的引用。從而這兩種類型存儲在內(nèi)存的不同地方。
其次從內(nèi)存空間上看,值類型是在棧中操作,而引用類型則在堆中分配存儲單元。
棧在編譯的時候就分配好內(nèi)存空間,在代碼中有棧的明確定義,而堆是程序運行中動態(tài)分配的內(nèi)存空間,可以根據(jù)程序的運行情況動態(tài)地分配內(nèi)存的大小。因此,值類型總是在內(nèi)存中占用一個預定義的字節(jié)數(shù)。而引用類型的變量則在棧中分配一個內(nèi)存空間,這個內(nèi)存空間包含的是對另一個內(nèi)存位置的引用,這個位置是托管堆中的一個地址,即存放此變量實際值的地方。
也就是說值類型相當于現(xiàn)金,要用就直接用,而引類型相當于存折,要用得先去銀行取。
但值類型在棧上分配內(nèi)存,而引用類型在托管堆上分配內(nèi)存,只是一種籠統(tǒng)的說法。下面對其進行詳細描述。
(1)對于值類型的實例,如果作為方法中的局部變量,則被創(chuàng)建在線程棧上;如果該實例作為類型的成員,則作為類型成員的一部分,連同其他類型字段存放在托管堆上。
每種值類型均有一個隱式的默認構(gòu)造函數(shù)來初始化該類型的默認值。例如:
int i = new int();
等價于:
Int32 i = new Int32();
等價于:
int i = 0;
等價于:
Int32 i = 0;
使用new運算符時,將調(diào)用特定類型的默認構(gòu)造函數(shù)并對變量賦以默認值。在上例中,默認構(gòu)造函數(shù)將值0賦給了i。
說明:C#的所有值類型均隱式派生自System.ValueType,而System.ValueType直接派生于System.Object。即System.ValueType本身是一個類類型,而不是值類型。其關鍵在于ValueType重寫了Equals方法,從而對值類型按照實例的值來比較,而不是引用地址來比較。
(2)引用類型的實例創(chuàng)建在托管堆上。
下面以一段代碼來詳細講解一下值類型與引用類型的區(qū)別
namespace Test { class Program { static void Main(string[] args) { //調(diào)用ReferenceAndValue類中的Demonstration方法 ReferenceAndValue.Demonstration(); Console.ReadLine(); } } public class stamp //定義一個類 { public string Name { get; set; } //定義引用類型 public int Age { get; set; } //定義值類型 } public static class ReferenceAndValue //定義一個靜態(tài)類 { public static void Demonstration() //定義一個靜態(tài)方法 { 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卻跟著變了,這就是值類型和引用類型的區(qū)別。在聲明age值類型變量時,將 Stamp_1.Age的值賦給它,這時,編譯器在棧上分配了一塊空間,然后把Stamp_1.Age的值填進去,二者沒有任何關聯(lián),就像在計算機中復制文件一樣,只是把Stamp_1.Age的值拷貝給age了。而引用類型則不同,在聲明guru時把Stamp_2賦給它,前面說過,引用類型包含的只是堆上數(shù)據(jù)區(qū)域地址的引用,其實就是把Stamp_2的引用也賦給guru,因此它們指向了同一塊內(nèi)存區(qū)域。既然是指向同一塊區(qū)域,不管修改誰,另一個的值都會跟著改變,就像信用卡跟親情卡一樣,用親情卡取了錢,與之關聯(lián)的信用卡賬上也會跟著發(fā)生變化。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持我們。
欄 目:C#教程
下一篇:C#強制轉(zhuǎn)換和嘗試轉(zhuǎn)換的方法
本文標題:C#中值類型和引用類型解析
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/5455.html
您可能感興趣的文章
- 01-10Extjs4如何處理后臺json數(shù)據(jù)中日期和時間
- 01-10C#及WPF獲取本機所有字體和顏色的方法
- 01-10同步調(diào)用和異步調(diào)用WebService
- 01-10C#編程自學之數(shù)據(jù)類型和變量二
- 01-10C#編程自學之數(shù)據(jù)類型和變量三
- 01-10C#編程自學之運算符和表達式
- 01-10C#裝箱和拆箱原理詳解
- 01-10C#編程自學之類和對象
- 01-10C#編程和Visual Studio使用技巧(下)
- 01-10C#編程自學之數(shù)據(jù)類型和變量一


閱讀排行
本欄相關
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻 器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實例總結(jié)
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個骰子