淺談C#中的值類(lèi)型和引用類(lèi)型
一、基本概念
C#只有兩種數(shù)據(jù)類(lèi)型:值類(lèi)型和引用類(lèi)型
值類(lèi)型在線(xiàn)程棧分配空間,引用類(lèi)型在托管堆分配空間
值類(lèi)型轉(zhuǎn)為引用類(lèi)型稱(chēng)成為裝箱,引用類(lèi)型轉(zhuǎn)為值類(lèi)型稱(chēng)為拆箱
以下是值類(lèi)型和引用類(lèi)型對(duì)照表
從上圖可以簡(jiǎn)單看出:string,Object,數(shù)組,class是引用類(lèi)型,簡(jiǎn)單類(lèi)型,枚舉,結(jié)構(gòu)是值類(lèi)型。
二、代碼展示
定義一個(gè)類(lèi)和結(jié)構(gòu)調(diào)用賦值
內(nèi)存分配情況如下圖:
從這張圖可以看出,class實(shí)例化出來(lái)的對(duì)象,指向了內(nèi)存堆中分配的空間;truct實(shí)例化出來(lái)的對(duì)象,是在內(nèi)存棧中分配。
修改代碼如下:
內(nèi)存分配情況:
由上圖可以知:
object obj=”abc”;
string i=(string)obj;
值類(lèi)型和引用類(lèi)型儲(chǔ)的位置不一樣
如果是引用類(lèi)型,當(dāng)兩個(gè)對(duì)象指向同一個(gè)地方,修改某一個(gè)的時(shí)候,其它對(duì)象的值會(huì)發(fā)生改變
using System; namespace ConsoleApplication2 { //引用類(lèi)型(因?yàn)椤甤lass') public class SomeRef { public int x { get; set; } } //值類(lèi)型(因?yàn)椤畇truct') public struct SomeVal { public int x{ get; set; } } class Program { static void Main(string[] args) { SomeRef r1=new SomeRef(); //在堆上分配 SomeVal v1 = new SomeVal();//在棧上分配 r1.x = 5; //提領(lǐng)指針 v1.x = 5; //在棧上修改 Console.WriteLine(r1.x); //顯示5 Console.WriteLine(v1.x); //顯示5 SomeRef r2 =r1; //只復(fù)制引用(指針) SomeVal v2 =v1; //在棧上分配并賦值成員 r1.x = 8; //r1.x和r2.x都會(huì)修改 v1.x = 8; //v1.x會(huì)更改,v2.x不會(huì) Console.WriteLine(r1.x); //顯示8 Console.WriteLine(r2.x); //顯示8 Console.WriteLine(v1.x); //顯示8 Console.WriteLine(v2.x); //顯示5 Console.ReadKey(); } } }
三、值類(lèi)型裝箱、拆箱
1、裝箱:就是將值類(lèi)型的數(shù)據(jù)打包到引用類(lèi)型的實(shí)例中(比如將string類(lèi)型的值abc賦給object對(duì)象obj)
object obj=(object)i;
裝箱時(shí)到底發(fā)生的事情:
1)、在托管堆中分配內(nèi)存。分配的內(nèi)存量是值類(lèi)型各字段所需的內(nèi)存量,還要加上托管堆所有對(duì)象都有的兩個(gè)額外成員(類(lèi)型對(duì)象指針和同步塊索引)所需的內(nèi)存量
2)、值類(lèi)型的字段復(fù)制到新分配的堆內(nèi)存
3)、返回對(duì)象地址,現(xiàn)在該地址是對(duì)象引用;值類(lèi)型成了引用類(lèi)型
2、拆箱:就是從引用數(shù)據(jù)中提取值類(lèi)型(比如將object對(duì)象obj的值賦給string類(lèi)型的變量i)
string i=(string)obj;
拆箱不是裝箱過(guò)程倒過(guò)來(lái),拆箱的代價(jià)愛(ài)比裝箱低的多,拆箱是獲取指針的過(guò)程,該指針指向包含在一個(gè)對(duì)象中的原始值類(lèi)型。
拆箱后將堆中的字段包含的值復(fù)制棧的值類(lèi)型實(shí)例中。
3、值類(lèi)型變?yōu)橐妙?lèi)型不一定要裝箱,例如:
string str1 = "joye.net" + 26.ToString(); //tostring后不需要裝箱
感興趣的可以用IL看一下。
- C#值類(lèi)型、引用類(lèi)型中的Equals和==的區(qū)別淺析
- 淺析C# 中的類(lèi)型系統(tǒng)(值類(lèi)型和引用類(lèi)型)
- C#中值類(lèi)型和引用類(lèi)型解析
- c#基礎(chǔ)系列之值類(lèi)型和引用類(lèi)型的深入理解
- C#引用類(lèi)型和值類(lèi)型的適用場(chǎng)合和區(qū)別
- c#中值類(lèi)型和引用類(lèi)型的基礎(chǔ)教程
- C#基礎(chǔ)入門(mén)之值類(lèi)型和引用類(lèi)型的區(qū)別詳析
- C#字符串與數(shù)值類(lèi)型、字節(jié)數(shù)組的互相轉(zhuǎn)換實(shí)戰(zhàn)案例
- C# 值類(lèi)型的實(shí)現(xiàn)
相關(guān)文章
C#實(shí)現(xiàn)目錄跳轉(zhuǎn)(TreeView和SplitContainer)的示例代碼
本文主要介紹了C#實(shí)現(xiàn)目錄跳轉(zhuǎn)(TreeView和SplitContainer)的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Unity平臺(tái)模擬自動(dòng)擋駕駛汽車(chē)
這篇文章主要為大家詳細(xì)介紹了Unity平臺(tái)模擬自動(dòng)擋駕駛汽車(chē),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07C#創(chuàng)建安全的棧(Stack)存儲(chǔ)結(jié)構(gòu)
這篇文章主要為大家詳細(xì)介紹了C#創(chuàng)建安全的棧(Stack)存儲(chǔ)結(jié)構(gòu)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10基于C#動(dòng)態(tài)生成帶參數(shù)的小程序二維碼
在微信小程序管理后臺(tái),我們可以生成下載標(biāo)準(zhǔn)的小程序二維碼,提供主程序入口功能,在實(shí)際應(yīng)用開(kāi)發(fā)中,小程序二維碼是可以攜帶參數(shù)的,可以動(dòng)態(tài)進(jìn)行生成,本文小編就給大家介紹一下如何基于C#動(dòng)態(tài)生成帶參數(shù)的小程序二維碼,感興趣的朋友可以參考下2023-12-12通過(guò)C#調(diào)用cmd來(lái)修改服務(wù)啟動(dòng)類(lèi)型
可以使用System.ServiceProcess.ServiceController這個(gè)類(lèi)允許連接到正在運(yùn)行或者已停止的服務(wù)、對(duì)其進(jìn)行操作或獲取有關(guān)它的信息但是這個(gè)類(lèi)并沒(méi)有提供修改服務(wù)啟動(dòng)類(lèi)型的方法,可以通過(guò)C#調(diào)用cmd來(lái)修改2012-12-12