Rujukan biasa bersifat kuat: selama ada, objek tidak akan diklaim GC. Kadang kita justru ingin kebalikannya, misalnya cache data besar yang boleh dipakai ulang bila masih ada, tetapi boleh diklaim bila memori mulai penuh. WeakReference menjawab kebutuhan itu: rujukan lemah ini bisa membaca kondisi objek tanpa menahan objek dari pengklaiman.

Contoh: Rujukan Lemah Sebelum dan Sesudah GC #

csharp
var cache = BuatCache();

TampilkanPanjang(cache);

TungguSiklusGC();

Console.WriteLine($"Target tersedia: {cache.IsAlive}");

WeakReference BuatCache()
{
    var data = new byte[500];
    return new WeakReference(data);
}

void TampilkanPanjang(WeakReference cache)
{
    if (cache.Target is byte[] target)
        Console.WriteLine($"Target tersedia, panjang {target.Length}");
}

void TungguSiklusGC()
{
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();
}

Output yang Dihasilkan:

text
Target tersedia, panjang 500
Target tersedia: False

Mari kita bedah baris demi baris:

  1. BuatCache(): array dibuat di dalam method terpisah. Ketika method kembali, hanya WeakReference yang tersisa, sehingga tidak ada rujukan kuat ke array.
  2. cache.Target is byte[] target: sebelum GC berjalan, array masih ada di heap, sehingga pola ini berhasil membaca panjangnya, yaitu 500.
  3. TungguSiklusGC(): tiga panggilan ini memaksa satu siklus GC menyeluruh untuk keperluan eksperimen. Pada aplikasi nyata, pengklaiman terjadi sendiri tanpa dipanggil.
  4. cache.IsAlive: setelah array tidak dicakup rujukan kuat, GC mengklaimnya kembali dan IsAlive melaporkan False.

Keluarga API Rujukan Lemah #

WeakReference non-generik menyediakan Target bertipe object dan properti IsAlive. Versi generik WeakReference<T> lebih aman karena TryGetTarget mengembalikan target dengan tipe yang tepat dalam satu panggilan; versi ini dipakai sebagai contoh utama pada bab Weak References di section Garbage Collection. Ada juga ConditionalWeakTable yang menyimpan pasangan kunci-nilai dengan masa berlaku mengikuti kuncinya.

Perlu dicatat, rujukan lemah tidak mengurangi jumlah pekerjaan GC; objek yang dirujuknya tetap diperiksa pada setiap siklus. Keunggulannya ada pada kontrol usia: aplikasi tidak perlu mengelola pembuangan entri cache secara manual, karena GC yang mengklaim kembali memorinya saat tekanan memori meningkat.