標籤:c# 實值型別 參考型別 堆 棧
C#中值類型和參考型別的區別淺記
在C#中,變數的類型分為兩種,分別是值類型和參考型別。
值類型的變數直接儲存值,說得更具體一些,就是值類型變數在記憶體中直接儲存它們自身的值,如代碼所示,
int x = 2;
值類型變數x,在記憶體中的某處直接儲存了它自身的值:2。
參考型別的變數儲存的是對其對象的引用,更進一步說,就是參考型別變數在記憶體中直接儲存了一個指向它處的引用,而引用所指的對象則儲存在參考型別變數所指的記憶體中。如代碼所示,
public class Thing
{
int x;
}
Thing x = newThing();
參考型別變數x,在對它進行聲明時,會在記憶體中的某處分配一塊空間儲存它自身的內容,而我們所使用的變數x,實際上則是一個指向了它自身內容的引用。
注意,稍後我們會說到,參考型別的變數,它自身的內容總是儲存在堆中;而值類型的變數,它自身的值總是分配在聲明它的地方(可能在棧中,也可能在堆中)。
那麼,C#中的值類型與參考型別,都有哪些區別呢,讓我們來列舉一下。
1、因為值類型變數儲存的就是它自身的值,所以它總是包含一個值,不可為空;而參考型別變數儲存的是一個指向它處的引用,所以可以為空白(null),表示不包含值,即沒有指向記憶體中的任何地方。
2、參考型別直接繼承自System.Object類,與此不同,值類型直接繼承自System.ValueType類,而System.ValueType類直接繼承自System.Object類。作為所有類型的基類,System.Object類提供了一組方法,這些方法在所有類型中都能找到,如ToString方法等。System.ValueType類繼承了System.Object類,它並沒有添加任何新成員,而只是覆蓋了所繼承的一些方法,使其更適合於值類型。注意,我們可以使用Type.IsValueType屬性來判斷一個類型是否為值類型,如代碼所示
Thing x = new Thing();
if( x.GetType().IsValueType ) {
// Todo Something
}
3、參考型別對象和值類型對象,它們在記憶體中的儲存分配規則不同。參考型別對象總是分配在堆中;而值類型對象總是分配在它被聲明的地方:若值類型對象作為欄位被聲明,那麼它將跟隨其所屬的對象被分配;若值類型對象作為局部變數被聲明,那麼它將儲存在棧上。如代碼所示,
public class Thing
{
int x; // x作為欄位,x為值類型,跟隨參考型別的對象被分配,位於堆上
}
Thing x = new Thing();
int x = 2;// x作為局部變數,x為值類型,位於棧上
4、所有的值類型都是密封的(seal),無法派生出新類型,而參考型別則可以繼續派生。這也是值類型更適合於資料存放區,而參考型別更適合於定義行為的原因。
最後,把C#中值類型與參考型別的劃分全部列舉一下:
作為值類型的資料類型 |
bool byte char decimal double float int long short sbyte uint ulong ushort enum struct |
作為參考型別的資料類型 |
class object string interface delegate |
好了,關於C#中值類型與參考型別的區別暫時就記錄這麼多,後續若有補充還會繼續完善。