Statik Üyeler (Static Members) [ C# / VB.NET ]

.NET Framework’ta nesneler, statik(static) veya statik olmayan(non-static) üyelerden oluşur. Statik olmayan üyeler, class’tan türetilmiş nesnenin üyeleridir, sınıftan kaç nesne türetilmişse bu üyelerin o kadar kopyası bulunur, bir nesneye ait üyenin değerinin değişmesi, o üyenin diğer nesnelerdeki değerini etkilemez. Statik üyeler ise, doğrudan class’ın kendi üyeleri olup class’tan üretilen nesneden bağımsız hareket ederler. Tüm nesnelerin ulaşabileceği ortak bir bellek alanında tutulur. Bu nedenle statik üyelere erişmek için class’tan bir nesne oluşturmaya gerek yoktur. Bu da statik üyelerle işlem yapmayı hızlandırır. Bütün statik üyeler, değer veya referans türü olup olmamasına bakılmaksızın hafızanın heap alanı üzerinde depolanır. Bu heap alanına 8 byte’lık bir pointer işaret eder. Kaç tane instance’in yaratıldığı önemli olmayıp her zaman tek bir hafıza slotu varlık gösterir.
Durağan üyeler veya global değişkenler olarak ta tanımlanan statik üyeler, C# tarafında static, VB.NET tarafında shared anahtar sözcüğüyle deklare edilir. Statik üyelerin ilk değeri tanımlanmamışsa, çalışma zamanında üyenin tipine göre değer verilir yani sayısal bir data türüyse “sıfır”, nesne ise “nothing” veya “null”, boolean türündeyse “false” değeri atanır. Hatırlarsanız C#’ta metodlar içindeki yerel değişkenleri kullanmak için ilk değerlerini vermek zorundaydık. Fakat bu zorunluluk sınıflara ait değişkenler için geçerli değildir.
Sadece değişkenler değil, method, event, property’leri hatta C# 2.0 ile birlikte class’ları da statik olarak deklare edebiliriz. Statik üyeler, sınıfla birlikte yüklenir ve uygulama sonlandırılana kadar yaşarlar.

Class Islem
    Private _sayi As Integer

    Public Shared Sub KareAl(ByVal Sayi As Integer)
        Console.WriteLine("Sayının karesi :" + Sayi * Sayi)
    End Sub
End Class
class Islem
{
    private int _sayi;

    public static void KareAl(int Sayi)
    {
        Console.WriteLine("Sayının karesi :" + Sayi * Sayi);
    }//KareAl
} //Islem


Aşağıdaki örnekte Islem sınıfının MagazaKod, Indirim ve SiparisKod isimli üç değişkeni bulunmaktadır. MagazaKod ve Indirim, statik, SiparisKod ise statik olmayan üye olarak tanımlanmıştır. SiparisKod üyesine erişmek için sınıftan bir nesne üretmek gerekirken, MagazaKod ve Indirim üyelerine erişmek için doğrudan sınıfı kullanmak yeterlidir.

Sub Main()
    Console.WriteLine("Statik MagazaKod değeri : {0}", Islem.MagazaKod)

    'Console.WriteLine("Statik olmayan SiparisKod değeri : {0}", Islem.SiparisKod)
    'Bu satır "Reference to a non-shared member requires an object reference." hatasını verir. 

    Dim objIslem As New Islem
    Console.WriteLine("Statik olmayan SiparisKod değeri : {0}", objIslem.SiparisKod)

    Console.WriteLine("Statik Indirim değeri : {0}", Islem.Indirim)
End Sub

Class Islem
    Public SiparisKod As Integer = 45
    Public Shared MagazaKod As String = "ES2005"
    Public Shared Indirim As Boolean
End Class
public static void Main(){
	Console.WriteLine("Statik MagazaKod değeri : {0}", Islem.MagazaKod);

	//Console.WriteLine("Statik olmayan SiparisKod değeri : {0}", Islem.SiparisKod)
	//Bu satır "An object reference is required for the nonstatic field, method, or property 'Islem.SiparisKod'" hatasını verir. 

	Islem objIslem = new Islem();
	Console.WriteLine("Statik olmayan SiparisKod değeri : {0}", objIslem.SiparisKod);
	Console.WriteLine("Statik Indirim değeri : {0}", Islem.Indirim);
}//Main

public class Islem {
	public int SiparisKod = 45;
	public static string MagazaKod = "ES2005";
    public static bool Indirim;
}//Islem

Sonuç
Statik MagazaKod değeri : ES2005
Statik olmayan SiparisKod değeri : 45
Statik Indirim değeri : False

Durağan üyeler konusunda önemli bir nokta da şudur; bu üyelere, VB.NET tarafında bir instance yani bir nesne üzerinden erişilebilirken, C# tarafında bir nesne üzerinden erişilemez. Yukarıdaki örnek için;

Dim objIslem As New Islem
objIslem.MagazaKod = "RT45"
'Uygun bir tanımlama
Islem objIslem = new Islem();
objIslem.MagazaKod="s";
//"Static member 'Islem.MagazaKod' cannot be accessed with an instance reference; qualify it with a type name instead" hatasına neden olur

Statik metodlar sadece statik metodlara erişebilir. Örnekte Statik() isimli metod, Normal() isimli metoda erişmeye çalıştığında hata oluşacaktır.

Class Islem
    Public Shared Sub Statik()
        Normal() 'Bu satır hata verir.
    End Sub

    Sub Normal()
        'işlem kodları
    End Sub
End Class
public class Islem
{
    public static void Statik()
    {
        Normal(); //Bu satır hata verir.
    }

    public void Normal()
    {
        //işlem kodları
    }
}//Islem

Sadece normal metodlar değil constructor’ler de statik olarak tanımlanabilir. Statik constructor’ler;

    açık bir şekilde, doğrudan(explicitly) çağrılamaz bu yüzden private olarak tanımlanırlar,
    kaç nesne yaratılırsa yaratılsın sadece ilk nesnede bir kez çalıştırılır,
    parametre alamazlar,
    overload ve inherit edilemezler.
    sınıfa ait herhangi bir instance oluşturulmadan önce çalışırlar,
    sınıfa ait statik değişkenlerin initialize edilmesinden sonra ve diğer statik üyelerden önce yürütülürler
    herhangi bir access modifier ve parametre alamazlar

Static olarak tanımlanmış üyeler, sınıfla birlikte yüklenirler demiştik. Bunu statik olarak tanımlanmış constructor örneği yaparak görebiliriz. Aşağıdaki örnekte Islem sınıfının statik ve statik olmayan iki yapılandırıcısı bulunmaktadır.

Sub Main()
    Dim objIslem1 As New Islem
    Dim objIslem2 As New Islem
    Dim objIslem3 As New Islem
    Console.ReadLine()
End Sub

Class Islem
    Shared Sayac As Integer

    Shared Sub New()
        Console.WriteLine("Statik yapılandırıcı çalıştı.")
        Console.WriteLine("------------------------------")
    End Sub

    Public Sub New()
        Sayac += 1
        Console.WriteLine("{0}. Nesnenin yapılandırıcısı çalıştı.", Sayac)
    End Sub

End Class
public static void Main(){
	Islem objIslem1 = new Islem();
	Islem objIslem2 = new Islem();
	Islem objIslem3 = new Islem();
	Console.ReadLine();
}//Main

public class Islem {

	public static int Sayac;

	static Islem()
	{
		Console.WriteLine("Statik yapılandırıcı çalıştı.");
		Console.WriteLine("------------------------------");
	}

	public Islem() {
		Sayac += 1;
		Console.WriteLine("{0}. Nesnenin yapılandırıcısı çalıştı.", Sayac);
	}

}//Islem

Sonuç
Statik yapılandırıcı çalıştı.
------------------------------
1. Nesnenin yapılandırıcısı çalıştı.
2. Nesnenin yapılandırıcısı çalıştı.
3. Nesnenin yapılandırıcısı çalıştı.

Görüldüğü gibi sınıftan bir nesne oluşturmaya çalıştığımızda öncelikle statik constructor çalıştı daha sonra nesnenin normal constructorü çalıştı. Statik üyeler, sınıfa ait olduğu için ne kadar nesne oluşturulursa oluşturulsun statik constructor bir kere yüklenir ve tüm nesneler aynı adrese erişir.

Statik Üyeler (Static Members) [ C# / VB.NET ]” üzerine bir düşünce

  1. Melih

    Konunun en can alıcı noktaları ve incelikleri güzel örneklerle pekiştirilerek anlatılmış, teşekkürler.

    Cevapla
  2. Birol

    Static ve shared taglarının ne gibi farkları olduğunu araştırıyordum. Baya açıklayıcı anlatmışsınız. Konuyu kavramamıza yardımcı olduğunuz için teşekkür ederim.

    Cevapla
  3. Salih Bal

    ÖNemli noktaları üzerine basa basa belirtmişsiniz. Klasik konu anlatımlarından uzak ama çok güzel bir yazı.

    Cevapla

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Time limit is exhausted. Please reload CAPTCHA.