Tipe item data menentukan dua hal: ukuran memori (jumlah bit) yang dibutuhkan untuk menyimpannya, serta anggota data yang dimiliki tipe tersebut. Selain itu, tipe juga mengatur lokasi penempatan objek di memori, yaitu di Stack (Tumpukan) atau Heap (Tumpukan Besar).
Tipe dibagi menjadi dua kelompok utama: Tipe Nilai (Value Types) dan Tipe Referensi (Reference Types). Cara penyimpanan dua jenis objek ini di memori sangat berbeda satu sama lain.
1. Tipe nilai hanya menggunakan satu blok memori, blok ini langsung menyimpan data asli tanpa perantara.

2. Tipe referensi memerlukan dua bagian memori terpisah:
- Bagian pertama menampung data asli objek dan bagian ini selalu dialokasikan di Heap;
- Bagian kedua adalah alamat referensi yang menunjuk posisi data di heap. (Stack hanya menyimpan alamat heap, pada masa bahasa C bagian ini disebut pointer atau penunjuk)

Dua gambar di atas hanya berlaku jika objek tidak menjadi anggota data dari objek lain.
Catatan Penting
Bagian data utama objek tipe referensi akan selalu ditempatkan di heap, sesuai gambar di atas.
Namun instansi tipe nilai atau alamat referensi tipe referensi bisa berada di stack maupun heap, tergantung bagaimana kode ditulis.
Contoh:
Misalkan ada tipe referensi Person yang memiliki dua anggota: satu anggota tipe nilai dan satu anggota tipe referensi.
Banyak orang salah paham dan mengira anggota tipe nilai ada di stack, alamat referensi juga di stack, sedangkan data utama objek ada di heap (seperti gambar di atas), namun pemikiran ini salah.
Ingat satu aturan: Semua data utama instansi tipe referensi akan selalu dialokasikan di heap. Kedua anggota termasuk dalam data utama objek ini, jadi baik tipe nilai maupun tipe referensi semuanya akan disimpan bersama di heap.
Contoh kode:
class Program
{
static void Main(string[] args)
{
int a = 10;
Person bill = new Person("Bill", 18);
}
}
class Person
{
private string name;
private int age;
private Phone myPhone;
public Person(string name, int age)
{
this.name = name;
this.age = age;
this.myPhone = new Phone();
this.myPhone.number = 12345;
}
}
class Phone
{
public long number;
}Code language: JavaScript (javascript)
Lihat contoh di atas, kelas Person memiliki tipe bawaan age dan name, serta tipe buatan sendiri bernama Phone. Tipe Phone sendiri memiliki tipe bawaan long untuk menyimpan nomor telepon genggam.
Pembaca mungkin melihat int age di dalam Person atau long number di dalam Phone lalu mengira keduanya tipe nilai sehingga tersimpan di stack, padahal tidak. Meskipun keduanya tipe dasar bawaan, karena menjadi anggota dari tipe kelas buatan, mereka akan ikut tersimpan di heap bersama instansi objek. Susunan penyimpanan akhirnya akan seperti ini:

Pelajari hal ini: Semua anggota data tipe buatan akan tersimpan di heap, tanpa peduli apakah tipe nilai atau tipe referensi. Jika ada anggota tipe referensi di dalam kelas seperti myPhone pada contoh, variabel tersebut hanya menampung alamat objek lain yang ada di heap.
Jika di dalam tipe Phone ada tipe buatan lain, maka bagian memori Phone akan memiliki ruang tambahan untuk menyimpan alamat referensi tipe buatan tersebut.
Program dimulai eksekusi dari fungsi Main, alamat objek referensi tingkat paling atas disimpan di stack, kemudian objek berikutnya akan saling terhubung seperti rantai di heap.

Contoh lain
// Kelas tipe referensi
class MyType
{
public int A; // Anggota tipe nilai, tertanam di instansi MyType yang ada di heap
public Person B; // Anggota tipe referensi; penunjuk referensi disimpan di heap, data utama dialokasikan di bagian heap terpisah
}
class Person
{
public string Name;
}
void Test()
{
// Stack menyimpan penunjuk referensi milik myObj
MyType myObj = new MyType();
/*
Susunan Heap:
Objek MyType {
A: nilai int yang tertanam langsung
B: penunjuk referensi menuju instansi Person
}
Blok Heap terpisah: Person{ Name: ... }
*/
// Variabel lokal tipe nilai, dialokasikan langsung di stack
int localNum = 10;
}Code language: PHP (php)
Aturan di atas hanya berlaku untuk anggota data kelas, bukan fungsi di dalam kelas. Jika fungsi kelas memiliki variabel lokal atau objek referensi, variabel lokal tipe nilai dan alamat objek referensi tetap akan tersimpan di stack. Lihat kode berikut:
Lihat contoh berikut lagi:
using System.ComponentModel.DataAnnotations;
class Program
{
static void Main(string[] args)
{
int a = 10;
Person bill = new Person("Bill", 18);
bill.Calculate();
}
}
class Person
{
private string name;
private int age;
private Phone myPhone;
public Person(string name, int age)
{
this.name = name;
this.age = age;
this.myPhone = new Phone();
this.myPhone.number = 12345;
}
public int Calculate()
{
int one = 12;
int two = 23;
Phone myNewPhone = new Phone();
return one + two;
}
}
class Phone
{
public long number;
}Code language: PHP (php)
Saya menambahkan fungsi Calculate ke kelas Person pada kode ini. Di dalam fungsi terdapat variabel lokal tipe nilai dan tipe referensi yang dipanggil dari Main. Variabel ini bukan anggota kelas Person, melainkan variabel lokal milik fungsi. Untuk variabel lokal tipe nilai akan disimpan di stack, sedangkan alamat referensi tipe referensi lokal juga ada di stack.

Saat baris kode bill.Calculate(); dijalankan, susunan memori akan seperti gambar berikut

Bagian berwarna biru pada gambar adalah tempat penyimpanan variabel di dalam fungsi saat sedang berjalan.
Sekali fungsi selesai dijalankan, variabel-variabel lokal ini akan keluar dari stack dan susunan memori berubah seperti gambar berikut

Setelah fungsi Calculate selesai dan kendali kembali ke Main, semua variabel yang dibuat di dalam fungsi akan keluar dari stack dan hilang. Namun bagian data utama myNewPhone (bagian biru di gambar) tetap ada di heap. Yang keluar dari stack hanya alamat referensinya, data asli objek tidak langsung dihapus dan tetap menunggu proses pembersihan sampah GC di waktu yang tepat.
Tipe Nilai dan Tipe Referensi