Diziniz öbek üzerinde ayrılmıştır ve girişler kutulu değildir.
Karışıklığınızın kaynağı büyük olasılıkla, insanlar yığın üzerinde referans türlerinin ve yığın üzerinde değer türlerinin ayrıldığını söylemişlerdir. Bu tamamen doğru bir temsil değildir.
Tüm yerel değişkenler ve parametreler yığına ayrılır. Bu, hem değer türlerini hem de referans türlerini içerir. İkisi arasındaki fark sadece değişkende saklanan şeydir . Şaşırtıcı olmayan bir şekilde, bir değer türü için, türün değeri doğrudan değişkende saklanır ve bir referans türü için, türün değeri yığın üzerinde depolanır ve bu değere bir başvuru , değişkente depolanan değerdir.
Aynı şey alanlar için de geçerlidir. Birleştirilmiş türden (a class
veya a struct
) bir örnek için bellek ayrıldığında, her örnek alanı için depolama alanı içermelidir. Başvuru türü alanlar için, bu depolama alanı, değerin kendisinden sonradan ayrılacak değere bir başvuru içerir. Değer türü alanlar için bu depolama alanı gerçek değeri tutar.
Yani, aşağıdaki tipler verildiğinde:
class RefType{
public int I;
public string S;
public long L;
}
struct ValType{
public int I;
public string S;
public long L;
}
Bu türlerin her birinin değerleri 16 bayt bellek gerektirir (32 bit kelime boyutu olduğu varsayılarak). Alan I
her bir durumda değerini depolamak için 4 bayt alır, alan S
olarak referans olarak saklamak için 4 bayt alır ve alan L
değerini depolamak için 8 bayt alır. Yani her ikisinin değeri için hafıza RefType
ve ValType
şuna benzer:
0 ┌───────────────────┐
│ Ben │
4 ├───────────────────┤
│ S │
8 ├───────────────────┤
│ L │
│ │
16 └───────────────────┘
Şimdi türleri, bir işlevde üç yerel değişkenler olsaydı RefType
, ValType
ve int[]
bu gibi:
RefType refType;
ValType valType;
int[] intArray;
o zaman yığınız şöyle görünebilir:
0 ┌───────────────────┐
│ refType │
4 ├───────────────────┤
│ valType │
│ │
│ │
│ │
20 ├───────────────────┤
│ intArray │
24 └───────────────────┘
Bu yerel değişkenlere değerler atadıysanız, şöyle:
refType = new RefType();
refType.I = 100;
refType.S = "refType.S";
refType.L = 0x0123456789ABCDEF;
valType = new ValType();
valType.I = 200;
valType.S = "valType.S";
valType.L = 0x0011223344556677;
intArray = new int[4];
intArray[0] = 300;
intArray[1] = 301;
intArray[2] = 302;
intArray[3] = 303;
Sonra yığınınız şöyle görünebilir:
0 ┌───────────────────┐
│ 0x4A963B68 │ - refType'ın yığın adresi
4 ├───────────────────┤
│ 200 │ - "valType.I` değeri
│ 0x4A984C10 │ - "valType.S" öğesinin yığın adresi
│ 0x44556677 │ - düşük 32 bitlik "valType.L"
│ 0x00112233 │ - yüksek 32 bitlik "valType.L"
20 ├───────────────────┤
│ 0x4AA4C288 │ - "intArray" öğesinin yığın adresi
24 └───────────────────┘
Adresindeki 0x4A963B68
(değeri refType
) bellek şuna benzer:
0 ┌───────────────────┐
│ 100 │ - `refType.I` değeri
4 ├───────────────────┤
│ 0x4A984D88 │ - `refType.S'nin yığın adresi.
8 ├───────────────────┤
│ 0x89ABCDEF │ - düşük 32 bitlik `refType.L`
│ 0x01234567 │ - yüksek 32 bitlik `refType.L`
16 └───────────────────┘
Adresindeki 0x4AA4C288
(değeri intArray
) bellek şuna benzer:
0 ┌───────────────────┐
│ 4 │ - dizi uzunluğu
4 ├───────────────────┤
│ 300 │ - `intArray [0]`
8 ├───────────────────┤
1 301 │ - `intArray [1]`
12 ├───────────────────┤
│ 302 │ - `intArray [2] '
16 ├───────────────────┤
3 303 │ - `intArray [3] '
20 └───────────────────┘
Şimdi, intArray
başka bir fonksiyona geçtiyseniz , yığına itilen değer 0x4AA4C288
, dizinin bir kopyası değil , dizinin adresi olacaktır .