1.值型別和引用型別的原理
2.執行緒棧和託管堆
3.裝箱和拆箱
4.型別判等
c#的基本型別是按照資料在計算機記憶體是如何被分配來劃分,一種是值型別(value type)基礎型別是結構,使用中記憶體儲存在棧中,一種是引用型別(reference type)基礎型別是類,使用中記憶體儲存在堆中常用關鍵字new創造空間。還有一種特殊型別,這裡稱之為簡單型別,string型別是一種簡單的引用型別,它不需要new關鍵字創造可以直接來使用,還有一些特殊的值型別(****** type)別如byte啊int等,在system.int32結構型別中定義屬性和方法在int32型別中都可以呼叫,比如:int a= 1; int b = new int();。原因是因為所有的值型別隱式繼承了system.valuetype,它是乙個類....上面不是說值型別的基礎型別是個結構嗎,在c#**中是看不到這種繼承關係的,這個關係只能通過msil**才可以看到,所以說是隱式繼承的,才會有引用型別的操作。
這裡注意的是,棧(stack)是一種先進後出的資料結構,堆(heap)是用於引用型別分配空間的區域,創造乙個物件將該物件的位址傳給棧上的變數
值型別:列舉、結構(數值型別、bool、使用者自定義結構型別)
引用型別:關鍵字定義型別(類、介面、泛型、事件、委託)、內建引用型別(字串、物件、動態型別dynamic)
那麼型別在記憶體中如何表示和展現的呢?下面來看幾個例子
值型別:
引用型別:
從上面的簡單**和形象圖中可以得知,值型別直接存在棧裡面,而引用型別的位址存在棧裡面,值存在堆裡面,簡單的來說new乙個物件存在堆裡面。要值得注意的是類部類,new乙個新的物件,在該物件的裡面初始化類部類,該類部類的物件是也是存在堆裡面的,而它的引用位址的值是給到物件的變數。
知道值型別和引用型別在記憶體分布情況後我們接著來講講大神們津津樂道的執行緒棧、託管堆
執行緒棧、託管堆:
每個正在執行的程式都對應著乙個程序(process),在乙個程序內部,可以有乙個或多個執行緒(thread),每個執行緒都擁有一塊儲存資料、引數、區域性變數、傳進來的資料等,這個就是執行緒棧。建立乙個引用型別的時候,引用變數也利用棧,但這時棧包含的只是對另乙個記憶體位置的引用位址,這個位址指向堆的一塊區域,這個區域就是託管堆(跟託管**不是乙個概念,毫無關係)。等程式使用完或者是不再呼叫這個託管堆裡面的資料時,gc就會自動**空間,當然,c#也提供了手動**機制,這個可以到後面講講c#的記憶體**機制。
下面來看看例子:
class program
;ages = pro.age;
console.writeline("年齡:", ages);}}
裝箱和拆箱:裝箱:就是將乙個值型別轉換成等價的引用型別。
class program
}
msil**就不貼了,這裡說說它的執行過程
1)在堆上為新的物件例項分配乙個記憶體
2)將棧上值型別變數的值複製到堆上的物件中
3)將堆上建立的物件的位址返回給引用型別變數
拆箱:跟裝箱相反的操作,將乙個已近裝箱的引用型別轉換為值型別。
class program
}
過程:
1)獲取已裝箱物件的位址
2)將值從堆的物件中複製到棧上的值變數中。
這裡要注意幾個問題,裝箱和拆箱的操作都是在堆上進行的,執行速度相對來說比較慢,所以盡量避免無意義的拆箱裝箱操作。在同種型別中也存在這拆箱和裝箱操作,只不過是隱式的,可以省略,例如:int轉double,有些的轉換會丟失精度或者記憶體溢位等情況。
型別判等:
動手寫寫幾個案例試試
class program
,p1==p3?", p1 == p2, p1 == p3);//執行結果:p1==p2?false,p1==p3?true
console.writeline("p1equals(p2)?,p1equals(p3)?", p1.equals(p2), p1.equals(p3));//執行結果:p1equals(p2)?false,p1equals(p3)?true
console.writeline("i==d?", i == d);//執行結果:i==d?true
console.read();}}
從上面**,可以的出一些簡要的結論:
1.引用型別的判等是判斷棧上面引用,而不是堆上面的資料,判斷兩個物件是否相等一般用equals
2.由此可見引用型別在傳遞引數的時候是直接把引用傳過去的
3.值型別在判斷的時候是轉成同型別再去判斷的,由進度低的轉向進度高的
4.因此有些時候int型別和double型別做計算的時候,與我們想象中的結果有些小小的偏差,系統自動把int型別轉成了double型別做運算的
至此文章結束,祝大家永遠週末無bug
深入C 資料型別
源於 system value type家族 主要包括 基本資料型別和列舉型別 結構型別 對於值型別,不同的變數會分配不同的儲存控制項,並且儲存空間中儲存的是該變數的的值。改變乙個變數的值不會影響另乙個變數的值。源於 system object家族 主要包括 類 介面和陣列 如果直接賦值給其他變數,...
深入C 資料型別
值型別 源於system.valuetype 引用型別 源於system.object 結構中可以有字段也可以有方法 定義時,結構中的字段不能被賦初值 可以不用new,直接定義結構的物件即可 前提該屬性的型別不是數值型別 宣告結構的物件後,必須給結構的成員賦初值 結構體中沒有預設建構函式,但類中有預...
深入C 資料型別
一 值型別與引用型別 值型別源於system.valuetype家族,值型別包括基本資料型別,結構型別和列舉型別。值型別 在棧上儲存的真實的值。引用型別源於system.object家族,在c 中引用型別主要包括陣列 類 介面 string型別等。引用型別 在棧和堆上都要分配空間。值型別例題 1 c...