static menandai member yang dimiliki oleh tipe, bukan oleh object. Field instance ada sekali untuk setiap object; static field ada sekali saja, titik. Method instance berjalan pada sebuah object (order.Ship()); static method berjalan pada tipe (Math.Round(x)) dan sama sekali tidak butuh object.
Static field: satu salinan, dipakai bersama
Cara paling jelas untuk melihat perbedaannya adalah sebuah penghitung. Setiap Order punya Id sendiri, tetapi jumlah order yang sudah dibuat harus disimpan di tempat yang dipakai bersama.
Output:
Ana #1, Ben #2, Chen #3
Orders created: 3
Member static diakses lewat nama tipenya: Order.Created, bukan a.Created. C# tidak mengizinkan akses member static lewat sebuah instance (error CS0176), sehingga di tempat pemanggilan terlihat jelas bahwa nilainya dipakai bersama.
Static method
Static method tidak punya this. Ia hanya bekerja dengan parameternya dan dengan member static lainnya. Karena itu bentuk ini cocok untuk helper yang menghitung sesuatu dari input-nya:
Output:
61.38 EUR
7
Main sendiri adalah static: runtime memanggilnya sebelum ada object apa pun.
Error CS0120: kode static yang memakai member instance
Karena Main adalah static, pemula sering menemui error ini begitu mereka menambahkan method kedua:
class Program
{
int visits;
void Greet() { Console.WriteLine("Hello"); }
static void Main()
{
Greet(); // error CS0120: An object reference is required for the non-static field, method, or property 'Program.Greet()'
visits++; // error CS0120: An object reference is required for the non-static field, method, or property 'Program.visits'
}
}
Static method tidak punya object, jadi tidak ada visits yang bisa ditambahnya. Ada dua solusi, dan yang tepat tergantung pada jenis member-nya:
- Member itu memang data milik setiap object: buat object lalu pakai.
var app = new Program(); app.Greet(); - Member itu tidak butuh state object: tandai sebagai
static.static void Greet() { ... }
Menandai semuanya static agar error-nya hilang memang berhasil di program kecil, tetapi berubah menjadi state global di program sungguhan. Putuskan dengan bertanya apakah datanya milik satu object atau milik seluruh program.
Arah sebaliknya selalu diizinkan: method instance bebas memanggil member static.
Static class
Class yang dideklarasikan static hanya boleh berisi member static dan tidak pernah bisa dibuat instance-nya. Ia adalah kelompok fungsi dan konstanta yang punya nama.
Output:
77
100
True
Compiler menegakkan aturan ini: member instance di dalam static class adalah error CS0708, dan new padanya adalah error CS0712. Math, Console, File, Path, dan Enumerable semuanya static class. Extension method juga harus berada di static class.
Static constructor dan static readonly
Static field yang nilainya butuh lebih dari satu ekspresi bisa diisi di static constructor, yang dijalankan runtime sekali saja, sebelum tipe itu dipakai pertama kali:
Output:
Before first use
ShippingRates initialized
5.50
3
2026-01-01
readonly berarti field itu hanya bisa diisi di initializer-nya atau di static constructor. Setelah itu nilainya tidak bisa diganti, meskipun object yang ditunjuknya masih bisa diubah, dan itulah sebabnya dictionary tersebut dibuka sebagai IReadOnlyDictionary.
const vs static readonly
Keduanya memberimu nilai bernama yang dipakai bersama oleh seluruh program, dan perbedaannya ada pada kapan nilainya ditetapkan:
const | static readonly | |
|---|---|---|
| Nilai ditetapkan saat | kompilasi | program berjalan, sekali |
| Tipe yang diizinkan | angka, char, bool, string, enum, null | tipe apa pun |
| Otomatis static | ya (tidak bisa menulis static const) | dideklarasikan static secara eksplisit |
| Disalin ke assembly pemanggil | ya | tidak, dibaca dari field-nya |
Bisa dipakai di case switch dan argumen attribute | ya | tidak |
Baris soal penyalinan itu penting untuk library: jika assembly A mendeklarasikan public const int MaxItems = 50; dan assembly B memakainya, B berisi literal 50. Mengubah A menjadi 100 tidak berpengaruh apa pun pada B sampai B dikompilasi ulang. Untuk nilai yang mungkin berubah antarversi, lebih baik pakai static readonly.
using static
Directive using static (C# 6) mengimpor member static dari sebuah tipe, sehingga kamu bisa memanggilnya tanpa nama tipenya:
Output:
Area: 28.27
40
Hasilnya enak dibaca untuk kode yang banyak memakai matematika. Di tempat lain, pakailah secukupnya: WriteLine atau Parse tanpa nama tipe menyembunyikan dari tipe mana method itu berasal.
State static dan thread
Static field dipakai bersama oleh setiap thread di dalam proses. Menambah nilainya dari beberapa thread sekaligus bisa menghilangkan sebagian update, karena created++ terdiri dari membaca, menambah, dan menulis, dan dua thread bisa saling menyela di antara langkah-langkah itu. Pakai Interlocked.Increment(ref created) untuk penghitung, atau lock untuk hal yang lebih besar. Aplikasi web adalah tempat masalah ini paling sering muncul: setiap request berjalan di suatu thread, jadi static field yang menyimpan "pengguna saat ini" dipakai bersama oleh semua pengguna.
Satu hal halus lagi: di generic class, setiap tipe yang terbentuk punya static field sendiri. Cache<int>.Count dan Cache<string>.Count adalah dua field yang berbeda.
Kapan memakai static
Pemakaian yang baik:
- Helper murni yang menghitung hasil dari argumennya: pemformatan, konversi, validasi.
- Konstanta dan data lookup yang read-only yang dipakai bersama oleh program.
- Factory method, seperti
TimeSpan.FromMinutes(5)atauTemperature.FromCelsius(21)buatanmu sendiri. - Extension method.
Pemakaian yang buruk:
- State global yang bisa diubah (pengguna saat ini, keranjang belanja, pengaturan yang berubah). State seperti ini mengikat setiap bagian kode yang menyentuhnya dan membuat tes saling bergantung pada sisa data dari tes lain.
- Apa pun yang nanti ingin kamu ganti saat testing, seperti jam, database, atau pengirim email. Pemanggilan static tidak bisa diganti dengan versi palsu; instance yang diteruskan ke constructor bisa.
Pertanyaan yang sering diajukan
Apa arti static di C#?
Member static dimiliki oleh tipe itu sendiri, bukan oleh object mana pun. Hanya ada satu salinan static field, berapa pun jumlah object yang ada, dan static method dipanggil lewat nama tipenya (Math.Max(3, 7)) tanpa membuat instance. Static method tidak punya this, jadi tidak bisa memakai field instance secara langsung.
Apa itu static class di C#?
Class yang dideklarasikan static hanya boleh berisi member static dan tidak pernah bisa dibuat instance-nya (new padanya adalah error CS0712). Class seperti ini mengelompokkan fungsi-fungsi terkait yang tidak butuh state object, seperti Math, Console, atau File. Extension method wajib dideklarasikan di static class.
Bagaimana cara mengatasi "An object reference is required for the non-static field, method, or property"?
Itu adalah error CS0120: sebuah static method, sering kali Main, memakai member instance. Buat object lalu panggil member itu padanya (var app = new Program(); app.Run();), atau tandai member itu static jika ia tidak butuh data milik object tertentu.
Apa perbedaan const dan static readonly di C#?
const adalah konstanta saat kompilasi (angka, string, bool, enum) yang nilainya disalin ke setiap assembly yang memakainya. Field static readonly diisi sekali saat program berjalan, di initializer-nya atau di static constructor, dan bisa berisi tipe apa pun, seperti DateTime atau sebuah list. Pakai const untuk nilai yang tidak akan pernah berubah, dan static readonly untuk selebihnya.
Kapan sebaiknya memakai static di C#?
Pakai static untuk kode yang hanya bekerja dengan parameternya (helper murni seperti pemformat harga), untuk konstanta dan cache yang memang global bagi seluruh program, dan untuk factory method. Hindari static untuk apa pun yang menyimpan state per pengguna atau per request, atau yang nanti ingin kamu ganti saat testing: state bersama yang bisa diubah sulit dites dan tidak aman di banyak thread tanpa locking.