標籤:泛型 cells 數組 特殊 也有 body 回收 並且 int
1.實值型別(ValueType)
實值型別包括:數實值型別,結構體,bool型,使用者定義的結構體,枚舉,可空類型。
實值型別的變數直接儲存資料,分配在託管棧中。變數會在建立它們的方法返回時自動釋放,例如在一個方法中聲明Char型的變數name=’C’,當執行個體化它的方法結束時,name變數在棧上佔用的記憶體就會自動釋放
C#的所有實值型別均隱式派生自System.ValueType。
結構體:struct(直接派生於System.ValueType)。
數實值型別:整型,sbyte(System.SByte的別 名),short(System.Int16),int(System.Int32),long(System.Int64),byte(System.Byte),ushort(System.UInt16),uint(System.UInt32),ulong(System.UInt64),char(System.Char)。
浮點型:float(System.Single),double(System.Double)。
財務計算的高精度decimal型:decimal(System.Decimal)。
bool型:bool(System.Boolean的別名)。
使用者定義的結構體(派生於System.ValueType)。
枚舉:enum(派生於System.Enum)。
可空類型(派生於System.Nullable<T>泛型結構體,T?實際上是System.Nullable<T>的別名
2.參考型別(ReferenceType)
參考型別包括:數組,使用者定義的類、介面、委託,object,字串,null類型,類。
參考型別的變數持有的是資料的引用,資料存放區在資料堆,分配在託管堆中,變數並不會在建立它們的方法結束時釋放記憶體,它們所佔用的記憶體會被CLR中的記憶體回收機制釋放。
數組(派生於System.Array)
使用者需定義以下類型:
類:class(派生於System.Object);
介面:interface(介面不是一個“東西”,所以不存在派生於何處的問題。介面只是表示一種contract約定[contract])。
委託:delegate(派生於System.Delegate)。
object(System.Object的別名);
字串:string(System.String的別名)。
3.實值型別與參考型別區別:
|
實值型別 |
參考型別 |
儲存方式 |
直接儲存資料本身 |
儲存的是資料的引用,資料存放區在資料堆中 |
記憶體配置 |
分配在棧中的 |
分配在堆中 |
效率 |
效率高,不需要地址轉換 |
效率較低,需要進行地址轉換 |
記憶體回收 |
使用完後立即回收 |
使用完後不立即回收,而是交給GC處理回收 |
賦值操作 |
建立一個新對象 |
建立一個引用 |
類型擴充 |
不易擴充,所有實值型別都是密封(seal)的,所以無法派生出新的實值型別 |
具有多態的特性方便擴充 |
執行個體分配 |
通常是線上程棧上分配的(靜態分配),但是在某些情形下可以儲存在堆中 |
總是在進程堆中分配(動態分配) |
實值型別和參考型別樹形結構:
註:給參數加了fef(out)後,參數是引用傳遞,這時候傳遞的是棧地址(指標,引用),否則就是正常的值傳遞---棧未經處理資料的拷貝。
4.記憶體配置
實值型別的執行個體經常會儲存在棧上的。但是也有特殊情況。如果某個類的執行個體有個實值型別的欄位,那麼實際上該欄位會和類執行個體儲存在同一個地方,即堆中。不過參考型別的對象總是儲存在堆中。如果一個結構的欄位是參考型別,那麼只有引用本身是和結構執行個體儲存在一起的(在棧或堆上,視情況而定)。
參考型別在棧中儲存一個引用,其實際的儲存位置位於託管堆。簡稱參考型別部署在託管推上。實值型別總是分配在它聲明的地方:作為欄位時,跟隨其所屬的變數(執行個體)儲存;作為局部變數時,儲存在棧上。實值型別在記憶體管理方面具有更好的效率,並且不支援多態,適合用做儲存資料的載體;參考型別支援多態,適合用於定義 應用程式的行為。
註:堆棧(stack)是一種後進先出的資料結構。在記憶體中,變數會被分配在堆棧上來進行操作。堆(heap)是用於為類型執行個體(對象)分配空間的記憶體地區,在堆上建立一個對象,會將對象的地址傳給堆棧上的變數(反過來叫變數指向此對象,或者變數引用此對象)。
5.裝箱和拆箱
1)裝箱就是將一個實值型別轉換成等值的參考型別
在堆上為新產生的對象(該對象包含資料,對象本身沒有名稱)分配記憶體。
將堆棧上實值型別變數的值拷貝到堆上的對象中。
將堆上建立的對象的地址返回給參考型別變數(從程式員角度看,這個變數的名稱就好像堆上對象的名稱一樣)。
2)拆箱就是將一個參考型別轉換成等值的實值型別
將參考型別變數堆上的值拷貝到棧上面。
總結
實值型別和參考型別理解透徹後,我們知道C#裡面是值傳遞,但是有些變數是參考型別的,在傳遞和拷貝時需要特別注意。方法傳遞參數時加上ref(out),為引用傳遞參數。
值傳遞僅僅傳遞的是值,不影響原始值。
引用傳遞,傳遞的是記憶體位址,修改後會改變記憶體位址對應儲存的值。
實值型別和參考型別