static bir nesneye değil tipe ait olan bir üyeyi işaretler. Bir örnek alanı nesne başına bir kez vardır; statik bir alan ise yalnızca bir kez vardır, o kadar. Bir örnek metodu bir nesne üzerinde çalışır (order.Ship()); statik bir metot tip üzerinde çalışır (Math.Round(x)) ve hiç nesneye ihtiyaç duymaz.
Statik alanlar: tek kopya, paylaşılan
Farkı görmenin en açık yolu bir sayaçtır. Her Order'ın kendi Id'si vardır, ama şimdiye kadar oluşturulan siparişlerin sayısı paylaşılan bir yerde yaşamak zorundadır.
Çıktı:
Ana #1, Ben #2, Chen #3
Orders created: 3
Statik üyelere tip adı üzerinden erişilir: a.Created değil Order.Created. C# statik bir üyeye bir örnek üzerinden ulaşmaya izin vermez (CS0176 hatası); bu da değerin paylaşıldığını çağrı yerinde açıkça gösterir.
Statik metotlar
Statik bir metodun this'i yoktur. Yalnızca parametreleriyle ve diğer statik üyelerle çalışır. Bu da onu girdilerinden bir şey hesaplayan yardımcılar için doğal şekil yapar:
Çıktı:
61.38 EUR
7
Main'in kendisi statiktir: çalışma zamanı onu herhangi bir nesne var olmadan önce çağırır.
CS0120 hatası: örnek üyelerini kullanan statik kod
Main statik olduğu için yeni başlayanlar ikinci bir metot eklediklerinde sık sık bu hatayla karşılaşır:
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'
}
}
Statik bir metodun nesnesi yoktur, bu yüzden artıracağı bir visits yoktur. İki çözüm vardır ve doğru olanı üyenin ne olduğuna bağlıdır:
- Üye gerçekten nesne başına veriyse: bir nesne oluşturun ve onu kullanın.
var app = new Program(); app.Greet(); - Üyenin nesne durumuna ihtiyacı yoksa: onu
staticişaretleyin.static void Greet() { ... }
Hatayı ortadan kaldırmak için her şeyi static işaretlemek küçük bir programda çalışır, gerçek bir programda ise global duruma dönüşür. Verinin bir nesneye mi yoksa tüm programa mı ait olduğunu sorarak karar verin.
Ters yön her zaman serbesttir: örnek metotları statik üyeleri serbestçe çağırabilir.
Statik sınıflar
static bildirilmiş bir sınıf yalnızca statik üyeler içerebilir ve asla örneklenemez. Adlandırılmış bir fonksiyonlar ve sabitler grubudur.
Çıktı:
77
100
True
Derleyici sözleşmeyi uygular: statik bir sınıfın içindeki bir örnek üyesi CS0708 hatasıdır ve onun üzerinde new CS0712 hatasıdır. Math, Console, File, Path ve Enumerable hepsi statik sınıflardır. Extension metotlar da statik bir sınıfta yaşamalıdır.
Statik constructor'lar ve static readonly
Değeri birden fazla ifade gerektiren statik bir alan, çalışma zamanının tip ilk kullanılmadan önce bir kez çalıştırdığı bir statik constructor'da ayarlanabilir:
Çıktı:
Before first use
ShippingRates initialized
5.50
3
2026-01-01
readonly, alanın yalnızca başlatıcısında ya da statik constructor'da atanabileceği anlamına gelir. Ondan sonra yeniden atanamaz, ama gösterdiği nesne yine de değiştirilebilir olabilir; dictionary'nin IReadOnlyDictionary olarak dışa açılmasının nedeni budur.
const ile static readonly
İkisi de tüm programın paylaştığı adlandırılmış bir değer verir ve değerin ne zaman sabitlendiği konusunda farklılaşırlar:
const | static readonly | |
|---|---|---|
| Değerin sabitlendiği an | derleme zamanı | çalışma zamanı, bir kez |
| İzin verilen tipler | sayılar, char, bool, string, enum'lar, null | her tip |
| Örtük olarak statik | evet (static const yazılamaz) | açıkça static bildirilir |
| Çağıran assembly'lere kopyalanır | evet | hayır, alandan okunur |
switch case'lerinde ve öznitelik argümanlarında kullanılabilir | evet | hayır |
Kopyalama satırı kütüphaneler için önemlidir: A assembly'si public const int MaxItems = 50; bildirir ve B assembly'si onu kullanırsa, B literal 50'yi içerir. A'yı 100'e değiştirmek B yeniden derlenene kadar B için hiçbir şey yapmaz. Sürümler arasında değişebilecek değerler için static readonly'yi tercih edin.
using static
Bir using static yönergesi (C# 6) bir tipin statik üyelerini içe aktarır, böylece onları tip adı olmadan çağırabilirsiniz:
Çıktı:
Area: 28.27
40
Yoğun matematik içeren kod için iyi okunur. Başka yerlerde idareli kullanın: çıplak bir WriteLine ya da Parse metodun hangi tipten geldiğini gizler.
Statik durum ve thread'ler
Statik bir alan süreçteki her thread tarafından paylaşılır. Birini birkaç thread'den aynı anda artırmak güncellemeleri kaybettirir, çünkü created++ bir okuma, bir toplama ve bir yazmadır ve iki thread bunları iç içe geçirebilir. Sayaçlar için Interlocked.Increment(ref created), daha büyük her şey için bir lock kullanın. Bunun ısırdığı olağan yer web uygulamalarıdır: her istek bir thread'de çalışır, bu yüzden "geçerli kullanıcı"yı tutan statik bir alan tüm kullanıcılar tarafından paylaşılır.
Bir incelik daha: generic bir sınıfta oluşturulan her tip kendi statik alanlarını alır. Cache<int>.Count ve Cache<string>.Count iki farklı alandır.
static ne zaman kullanılmalı
İyi kullanımlar:
- Argümanlarından bir sonuç hesaplayan saf yardımcılar: biçimlendirme, dönüşümler, doğrulama.
- Program tarafından paylaşılan sabitler ve salt okunur arama verileri.
TimeSpan.FromMinutes(5)ya da kendiTemperature.FromCelsius(21)'iniz gibi fabrika metotları.- Extension metotlar.
Kötü kullanımlar:
- Değiştirilebilir global durum (geçerli kullanıcı, bir alışveriş sepeti, değişen ayarlar). Ona dokunan her kod parçasını birbirine bağlar ve testleri birbirinin artıklarına bağımlı hale getirir.
- Testlerde değiştirmek isteyeceğiniz her şey, örneğin bir saat, bir veritabanı ya da bir e-posta gönderici. Statik çağrılar sahte bir sürümle değiştirilemez; constructor'a geçirilen bir örnek değiştirilebilir.
Sıkça Sorulan Sorular
C#'ta static ne anlama gelir?
static bir üye herhangi bir nesneye değil tipin kendisine aittir. Kaç nesne olursa olsun statik bir alanın tek bir kopyası vardır ve statik bir metot bir örnek oluşturmadan tip adı üzerinden çağrılır (Math.Max(3, 7)). Statik bir metodun this'i yoktur, bu yüzden örnek alanlarını doğrudan kullanamaz.
C#'ta statik sınıf nedir?
static bildirilmiş bir sınıf yalnızca statik üyeler içerebilir ve asla örneklenemez (onun üzerinde new CS0712 hatasıdır). Math, Console ya da File gibi nesne durumu gerektirmeyen ilgili fonksiyonları gruplar. Extension metotlar statik bir sınıfta bildirilmelidir.
"An object reference is required for the non-static field, method, or property" hatası nasıl düzeltilir?
Bu CS0120 hatasıdır: statik bir metot, çoğu zaman Main, bir örnek üyesini kullanıyor. Ya bir nesne oluşturup üyeyi onun üzerinde çağırın (var app = new Program(); app.Run();) ya da nesne başına veriye ihtiyacı yoksa üyeyi static işaretleyin.
C#'ta const ile static readonly arasındaki fark nedir?
const, değeri onu kullanan her assembly'ye kopyalanan bir derleme zamanı sabitidir (sayılar, string'ler, bool, enum'lar). static readonly bir alan ise çalışma zamanında, başlatıcısında ya da statik constructor'da bir kez atanır ve DateTime ya da bir liste gibi her tipi tutabilir. Asla değişmeyecek değerler için const, geri kalan her şey için static readonly kullanın.
C#'ta static ne zaman kullanılmalı?
Yalnızca parametreleri üzerinde çalışan kod için (fiyat biçimlendirici gibi saf yardımcılar), program için gerçekten global olan sabitler ve önbellekler için ve fabrika metotları için static kullanın. Kullanıcı başına ya da istek başına durum tutan ya da testlerde değiştirmek isteyeceğiniz hiçbir şey için static kullanmaktan kaçının: paylaşılan değiştirilebilir durumu test etmek zordur ve lock olmadan thread'ler arasında güvenli değildir.