C#只有兩種數據類型:值類型和引用類型編程
值類型在線程棧分配空間,引用類型在託管堆分配空間數組
值類型轉爲引用類型稱成爲裝箱,引用類型轉爲值類型稱爲拆箱網絡
如下是值類型和引用類型對照表ide
從上圖能夠簡單看出:string,Object,數組,class是引用類型,簡單類型,枚舉,結構是值類型。spa
2、代碼展現.net
定義一個類和結構調用賦值線程
內存分配狀況以下圖:3d
從這張圖能夠看出,class實例化出來的對象,指向了內存堆中分配的空間;truct實例化出來的對象,是在內存棧中分配。指針
修改代碼以下:code
內存分配狀況:
由上圖能夠知:
object obj=」abc」; string i=(string)obj;
值類型和引用類型儲的位置不同
若是是引用類型,當兩個對象指向同一個地方,修改某一個的時候,其它對象的值會發生改變
注意點:
一、值類型變量作爲局部變量時,該實例將被建立在堆棧上;而若是值類型變量做爲類型的成員變量時,它將做爲類型實例數據的一部分,同該類型的其餘字段都保存在託管堆上。
二、引用類型變量數據保存在託管堆上,可是根據實例的大小有所區別:當實例的大小小於85000Byte時實例將建立在GC堆上;當實例大小>=85000byte時,則該實例建立在LOH(Large Object Heap)堆上。
using System; namespace ConsoleApplication2 { //引用類型(由於‘class’) public class SomeRef { public int x { get; set; } } //值類型(由於‘struct’) 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; //提領指針 v1.x = 5; //在棧上修改 Console.WriteLine(r1.x); //顯示5 Console.WriteLine(v1.x); //顯示5 SomeRef r2 =r1; //只複製引用(指針) SomeVal v2 =v1; //在棧上分配並賦值成員 r1.x = 8; //r1.x和r2.x都會修改 v1.x = 8; //v1.x會更改,v2.x不會 Console.WriteLine(r1.x); //顯示8 Console.WriteLine(r2.x); //顯示8 Console.WriteLine(v1.x); //顯示8 Console.WriteLine(v2.x); //顯示5 Console.ReadKey(); } } }
一、裝箱:就是將值類型的數據打包到引用類型的實例中( 好比將int類型的值1賦給object對象obj)
int i=1; object obj=(object)i;
裝箱時到底發生的事情:
1)、在託管堆中分配內存。分配的內存量是值類型各字段所需的內存量,還要加上託管堆全部對象都有的兩個額外成員(類型對象指針和同步塊索引)所需的內存量
2)、值類型的字段複製到新分配的堆內存
3)、返回對象地址,如今該地址是對象引用;值類型成了引用類型
二、拆箱:就是從引用數據中提取值類型(好比將object對象obj的值賦給int類型的變量i)
object obj=」1」; int i=(int)obj;
拆箱不是裝箱過程倒過來,拆箱的代價要比裝箱低的多,拆箱是獲取指針的過程,該指針指向包含在一個對象中的原始值類型。
拆箱後將堆中的字段包含的值複製棧的值類型實例中。
三、值類型變爲引用類型不必定要裝箱,例如:
string str = "joye.net" + 26; //須要將26裝箱爲string類型 string str1 = "joye.net" + 26.ToString(); //tostring後不須要裝箱
感興趣的能夠用IL看一下。
《深刻理解C#》第二版
《CLR VIA C#》第四版
《C# 高級編程》第四版
還有不少網絡上的文章,就不一一例舉了