C#裏面的數據類型可分爲3大類:值類型,引用類型,指針類型。指針類型只能用於安全模式,所以我只用考慮前兩個。
值類型:結構類型,枚舉類型,簡單類型(包括整數類型,浮點類型,字符類型,decimal類型,布爾類型)
引用類型:類類型,接口類型,委託類型,數組類型。
值類型存在棧中,引用類型存在堆中。(在棧中不受垃圾回收機制的控制,而垃圾回收是要消耗時間的。)
值類型的賦值本質是拷貝,相當於C++裏面的深拷貝,引用類型的賦值僅僅是將棧上的指針拷貝,結果是兩個指針指向同一塊內存。
//代碼引自[(https://www.cnblogs.com/felixfang/p/3603094.html)]
private class SomeRef { public Int32 x; }//引用類型
private struct SomeVal { public Int32 x; }//值類型
public static void Go()
{
SomeRef r1 = new SomeRef(); // Allocated in heap
SomeVal v1 = new SomeVal(); // Allocated on stack
r1.x = 5; // Pointer dereference
v1.x = 5; // Changed on stack
Console.WriteLine(r1.x); // Displays "5"
Console.WriteLine(v1.x); // Also displays "5"
SomeRef r2 = r1; // Copies reference (pointer) only
SomeVal v2 = v1; // Allocate on stack & copies members
r1.x = 8; // Changes r1.x and r2.x
v1.x = 9; // Changes v1.x, not v2.x
Console.WriteLine(r1.x); // Displays "8"
Console.WriteLine(r2.x); // Displays "8"
Console.WriteLine(v1.x); // Displays "9"
Console.WriteLine(v2.x); // Displays "5"
解惑:類型的裝箱和拆箱
值類型對象有兩種狀態(unboxed,boxed),引用類型只有一種(boxed)。
在ArrayList中,所有的元素類型都爲object類型,如果是值類型的話,就會引起CLR的拆箱和裝箱。
因爲在ArrayList中值類型的數據會被當作引用類型對待(也就是能繼承,在ArrayList中繼承的是object,而值類型是不能夠繼承或者被繼承的),裝箱後的值類型就和引用類型沒區別,在堆中也有自己的內存。棧中存放的是引用地址。
但是裝箱拆箱過程需要有一定的性能開銷,很不好。