in Eski Blog Yazılarım

Struct’dan haberdar olmanız yetmez, kullanmanız gerekir

Yazılım
geliştirirken bizi sırtlayan programlama çatısının özelliklerini tek
tek ve çok ayrıntılı bilmemiz her zaman mümkün olmuyor, fakat bazı
özellikler var ki hem geliştirilen programın kalitesini, hem de
performansını büyük ölçüde etkileyebiliyor. Bu etkiyi C# programlama
dilinde yaratabilecek özelliklerden bir tanesi de Struct (Yapı) veri
tipidir ve konuda budur.

Bilindiği gibi Struct ile yapılabilen
her işlemi ve daha fazlasını Class ilede yapılabiliyor. Peki neden
Struct kullanalım? diye sorabilirsiniz. Aşağıda bu sorunun cevabını
kendi tecrübelerime dayanarak vermeye çalıştım.

  • Struct
    bir değer türü olduğu için oluşturulduğunda Stack bellek bölgesinde
    tutulur. Stack bellek bölgesinde yeni bir nesne tanımlamak ve nesneye
    erişmek, class’ların tutulduğu Heap bölgesinden daha hızlıdır.
  • Programın
    struct nesnesi ile işi bittiğinde Garbage Collector anında devreye
    girip lazım olmayan struct nesnelerini temizler. Böylece siz programcı
    olarak bu kaynağı işi bitti diye tekrar serbest bırakmak zorunda
    kalmazsınız.
  • Algoritmanızda Birden fazla değişkeniniz varsa
    bunları tek tek yönetmek yerine Struct ile bu değişkenleri tek bir
    veritipi haline getirebilirsiniz.
  • Ben OOP‘nin tüm
    nimetlerinden yararlanmak istiyorum ama struct kadar performanslı da
    olsun diyorsanız yine struct içinde method, constructor, değişken ve
    indexleyici kullanabilrisiniz.
  • Struct, aynı class gibi private, public, internal, protected, protected internal değerlerini alabilir.
  • Struct’lar İçiçe tanımlanabilir (Nested Structure) hemde çok zevkli olur.

Tabi
Struct’ı her zaman kullanacağız diye bir şey yok, sadece işimize
geldiği zaman kullanalım. Bazı durumlarda da aşağıdaki nedenlerden
dolayı hiç kullanmamalıyız.

  • Struct’lar bir birlerinden türeyemez (Inheritance) ama birden fazla Interface’den türeyebilir.
  • Struct’lar
    da yapıcı (Constructor) method varsayılan olarak parametresizdir ama
    yinede siz kendi parametrik yapıcı metodlarınızı tanımlamayabilirsiniz.
    Herhalükarda varsayılan yapıcı metod çalışacaktır.
  • Programınız içinde nesneler arası bağlantı, kompleks ilişkiler varsa struct kullanmamalısınız.
  • Struct’lar da statik üye tanımlayabilirsiniz ama nesneyi yarattıktan sonra erişemezsiniz.

Struct’lar
neredeyse her yönü ile Class’lara benzerler yalnız class’lardan biraz
daha kısıtlıdır ama daha da hızlıdır. Yukarıdaki maddeler size nerede
struct kullanmanız gerektiği hakkında az çok fikir verebilir ama doğru
karar vermeniz için tecrübeniz olması gerekir çünkü bu meslekte tecrübe
herşeydir ;)

Class ve Struct’ı basitçe karşılaştırıp aradaki
farkı performans açısından ele almak için basit bir test programı
hazırladım bakalım sonuç nasıl çıkacak.?

    class Program
    {
        class clsHayvanlar
        {
            public string a { get; set; }
        }

        struct srtHayvanlar
        {
            public string a { get; set; }
        }

        static void Main(string[] args)
        {
            string tmp_ = string.Empty;            
            Stopwatch s1 = new Stopwatch();
            s1.Start();

            List cls_list = new List();
            for (int i = 0; i < 1000000; i++)
            {
                cls_list.Add(new clsHayvanlar() { a = "value" });// Heap bellek bölgesinde yer ayrılıyor.
                tmp_ = cls_list[i].a; // Heap bölgesinden okunuyor.
            }
            s1.Stop();

            Console.WriteLine("classt: {0:N2}",s1.ElapsedMilliseconds);

            Stopwatch s2 = new Stopwatch();
            s2.Start();

            List str_list = new List();
            for (int i = 0; i < 1000000; i++)
            {
                str_list.Add(new srtHayvanlar() { a = "value" }); // Stack bellek bölgesinde yer ayrılıyor.
                tmp_ = str_list[i].a; // Stack bölgesinden okunuyor.
            }
            s2.Stop();

            Console.WriteLine("structt: {0:N2}",s2.ElapsedMilliseconds);
        }
    }

—————–
class   : 232,00 ms
struct  : 90,00 ms

Görüldüğü gibi Struct lehine bariz fark var ama bu durumun tam tersi olduğu zamanlarda olabiliyor tabi bu ayrı bir yazı konusu.

Ben
genelde Struct’ı dağınık verileri toparlamak, çoğu zamanda yeni bir
veri türü oluşturmak için kullanıyorum, gerisi zaten GC’a ve
Framework’e kalıyor. Genelde kullandığım yapı aşağıdaki gibi. Yeni bir
veri türüne ihtiyacım varsa bu türü yaratırken Struct kullanmam işimi
fazlasıyla görüyor.

    class Program
    {
        static List d_list;
        static void Main(string[] args)
        {
            d_list = new List(Directory.GetFiles(".\").Length);

            foreach (var item in Directory.GetFiles(".\"))
            {
                d_list.Add(new sistem_dosyasi(
                    new FileInfo(item)));
            }
        }

        struct sistem_dosyasi
        {
            public long size;
            public string name;

            public sistem_dosyasi(FileInfo fi)
            {
                this.size = fi.Length;
                this.name = fi.Name;
            }
        }
    }

Yorum Bırak

Comment