Yazılım Mimarileri ve Tasarım Desenleri Üzerine

C# Non-Generic Koleksiyon Yapıları – System.Collections

Bu yazımda C#’ta koleksiyon yapılarından bahsedeceğim..NET Framework içinde koleksiyon yapıları System.Collections namespace i altında bulunan veri saklama sınıflarıdır.İki tür koleksiyon yapısı vardır.Non-Generic ve Generic koleksiyonlar.Ben bu yazımda Non-Generic koleksiyonlardan bahsedeceğim.Bu koleksiyon sınıfları;ArrayList,SortedList ve HashTable dır.Bu koleksiyonlar klasik diziler gibidirler.Ancak dizilerde(Array) kullanamadığımız bir çok özelliği bu koleksiyon yapılarında kullanabiliyoruz.

Neden diziler değilde koleksiyon yapılarını tercih etmemiz gerekiyor?
Bir dizi oluştururken eleman sayısını belirtmemiz gerekiyor.Eleman sayısını aşarsak eğer, bize hata veriyor.Bu da bizi hem sınırlıyor, hem de verdiğimiz o boyutta bellekte yer kaplıyor.Ancak bir koleksiyon yapısında, biz o koleksiyona eleman verdikçe boyutu dinamik şekilde ayarlanır.
Şunuda belirtmek istiyorum.Her ne kadar dizilerde bizi sınırlıyor ve bellekte yer kaplıyor desekte,sonucta tek bir tipten dizi oluşturabildiğimiz için Casting işlemi hiç yapılmıyor.Ancak Non-Generic koleksiyonlarda object tipten eleman aldığı için Boxing-Unboxing işlemleri uygulamak zorunda kalıyoruz.Buda Non-Generic koleksiyonlara karşı bir artısı var demektir.
Aslında bu yazımda sadece Non-Generic koleksiyonlardan bahsedeceğim ama Generic koleksiyonlar hakkında da bilgi vermeden yapamayacağım.Günümüzde genellikle Non-Generic koleksiyonlar yerine Generic koleksiyonlar tercih edilir.Çünkü yukarıda bahsettiğimiz gibi Non-Generic koleksiyonlarda object tiple çalışırlar ve sürekli Boxing ve Unboxing işlemleri yapılır.Yani tip güvenli değildir.Fakat Generic’ler içlerinde olacak tiplerin ne olduğunu belirtebileceğimiz için tip güvenlidirler(Generic koleksiyonlara ilerideki yazılarımda değineceğim.).Buda şunu gösteriyor ki,dizi yerine Generic koleksiyon kullanmak,bizlere daha esnek yapı sunacaktır.

Bir sonraki sayfada System.Collections isim alanıyla ilgili açıklama yapacağım.

System.Collections İsim Alanı
Non-Generic koleksiyonların bulunduğu bir namespacedir.
System.Collections isim alanında bir çok arayüz bulunmaktadır.
Bu arayüzlerin ne olduklarını ve ne işe yaradıklarını inceleyelim..
Öncelikle şunu belirtmek istiyorum ki,bütün koleksiyon sınıfları birazdan anlatmaya başlayacağım arayüzlerden bir ya da birden fazlasını uygulamıştır.İleride göreceğimiz koleksiyon sınıflarının ortak özellik ve metodlarının sebebi, uygulanan arayüzlerin aynı olmasıdır.
ICollection
Bu arayüz, bir koleksiyonda olabilecek en temel metod ve propertyleri içerir.System.Collection isim alanında bulunan tüm sınıflar bu arayüzü uygulamıştır.ICollection arayüzü,IEnumerable arayüzünden kalıtım almıştır.Bu sebepten dolayı ICollection arayüzünü uygulayan sınıflar,IEnumerable arayüzünüde uygulamak zorundadır.


IComparer
Birden fazla nesnenin sıralanabilmesi için nesnelerin karşılaştırılabilir olması gerekiyor.Örneğin, bir sayı diğer sayıdan ya daha büyüktür, ya daha küçüktür ya da eşittir.Bu mantıkla bir int dizisi sıralanabilir.Aynı karşılaştırma mantığı string ifadeler içinde geçerlidir.”Ahmet” her zaman “Mustafa” dan önce gelir.Buradada alfabetik karşılaştırma söz konusudur.

Peki yarattığımız herhangi bir classın birden fazla nesnesini nasıl sıralayabiliriz.Örneğin, “Personel” isimli bir classımız var.Ve bu classta “PersonelAdi”,”PersonelSoyadi” ve “PersonelID” adında üç tane property mevcut.Bu özelliklerdeki classımızdan beş tane nesne oluşturuyorum.Bu nesneleri nasıl sıralayabilirim.Program bunları “PersonelAdi” na göremi,”PersonelSoyadi” na göremi yoksa “PersonelID” sine göremi sıralayacak.İşte bu sorunu bu arayüz sayesinde çözebiliyoruz.


IDictionary
Bu arayüzü bir key – value ikilisi gibi çalışan koleksiyon sınıfları uygularlar.HashTable gibi koleksiyon tiplerini anlatırken key – value ikilisinin ne demek olduğunu anlayacaksınız.IDictionary arayüzü ICollection arayüzünden türemiştir.Bu yüzden IDictionary arayüzünü uygulayan bir sınıf ICollection arayüzündeki metod ve propertyleri de uygulamalıdır.


IDictionaryEnumerator
Bu arayüz ile key – value ikili çiftlerden sadece key, sadece value ya da hem key hem value anahtar çiftlerini elde etmek için Value, Key ve Entry isimli 3 tane özellik bulunur.


IEnumerable
Bir koleksiyon tabanlı sınıfın elemanları arasında ilerlemek için kullanılan GetEnumerator() metodunu tanımlar.


IEnumerator
Bir koleksiyon sınıfı için koleksiyondaki her bir elemana erişmek ve diğer işleri yapmak için uygulanması gereken arayüzdür.
Koleksiyonlar içindeki elemanlar for,foreach ile dönülebilir.Aynı zamanda IEnumarator referansı üzerinden de dönülebilir.GetEnumarator() metodu ile koleksiyonun IEnumarator’ü talep edilir.

            ArrayList liste = new ArrayList();
            for (int i = 1; i <= 5; i++)
            {
                liste.Add(i);
            }

Yukarıdaki kodu incelerseniz,liste adındaki ArrayList’imiz 1’den 5’e kadar dolduruluyor.

            IEnumerator elemanlar = liste.GetEnumerator();

ArrayList içindeki elemanlara teker teker ulaşabilmek için IEnumerator arayüzünün referansına ihtiyaç duyuyoruz.GetEnumerator() metoduyla veriler teker teker ulaşıyoruz.
Artık ArrayList içindeki elemanlara IEnumerator arayüzü tipinden olan “elemanlar” referansından ulaşmak mümkün.
Şimdi “elemanlar” referansımızın metod ve özelliklerine bakalım.
MoveNext() metodu : Kolesiyon içinde dolaşacak başka eleman var mı? diye sorar.Varsa True yoksa False döndürür.
Current özelliği : O an üzerinde bulunulan elemanı verir.
Reset() metodu : Koleksiyonun ilk elemanına kafayı konumlandırır.

            while (elemanlar.MoveNext())
            {
                MessageBox.Show(elemanlar.Current + "");
                if ((int)elemanlar.Current == 5)
                {
                    elemanlar.Reset();
                }
            }

IList
Bu arayüz, bir koleksiyondaki elemanların her birine sıfır tabanlı bir indeks ile erişebilmek için çeşitli metodlar ve özellikler içerir.IList,ICollection arayüzünden türetilmiştir.


IHashProvider
Bu arayüz Object sınıfındaki GetHashCode() metodunu tanımlar.Bu metod ile HashTable sınıfı ile çalışabilmek için bir kod üretilir.Hash kodu denilen bu kodun ne anlama geldiğini HashTable sınıfında anlayacaksınız.
Şimdi Non-Generic koleksiyon yapılarını incelemeye başlayalım.
Bir sonraki sayfada ArrayList koleksiyon yapısını inceleyeceğiz.


ArrayList
Koleksiyon sınıflarının en genel amaçlı olanıdır.Dizilere oldukça benzerler.Tek farkı dizilerde eleman sayısı başta belirtilirken,ArrayList’te eklenen elemana göre eleman sayısı artar.ArrayList ilk oluşturulduğunda kapasite 0,sonra eleman eklendiğinde kapasite 4 olur.Eleman sayısı 4 ü geçtikten sonra kapasite iki kat olarak artmaya başlayacaktır.0,4,8,16,32..
ArrayList koleksiyonu ICollection, IEnumerable, IList ve ICloneable interfacelerini(arayüz) uygular.
Arraylistin üç tane yapıcı metodu mevcuttur.

ArrayList liste = new ArrayList();

Bu şekilde oluşturulan ArrayList koleksiyonunda,eleman eklendikçe kapasite otomatik olarak artacaktır.

ArrayList liste = new ArrayList(40);

Bu şekilde oluşturulan ArrayList koleksiyonunda,kapasite başlangıçta 40 tır.Eleman sayısı 40 ı geçerse otomatik olarak arttırılmaya başlar.

ArrayList liste = new ArrayList(ICollection c);

Bu şekilde oluşturulan ArrayList koleksiyonunda,ICollection arayüzünü uygulamış herhangi bir sınıfın nesnesi parametre olarak verilir.

ArrayList koleksiyonu, içine aldığı elemanları object tipte kabul eder.Yani bir Boxing işlemi görülmektedir.Bu elemanları kullanırken mecburen Unboxing işlemi yapmamız gerekecektir.
Add Metodu
Bir ArrayList koleksiyonuna eleman eklemek için Add() metodu kullanılır.Bu metod object tipte parametre alır.Bu parametreye elemanızı veririz(Bu eleman herhangi bir sınıfın nesneside olabilir.)Ve bu elemanı koleksiyonumuzun en sonuna ekler.

            ArrayList liste = new ArrayList();
            liste.Add(1);
            liste.Add(2);
            liste.Add(3);

Remove Metodu
Bir ArrayList koleksiyonundan eleman silmek için Remove() metodu kullanılır.Bu metod object tipte parametre alır.Bu parametreye verilen değerdeki eleman koleksiyondan çıkartılır.Eğer verilen değer bulunamazsa hata oluşmaz, program işleyişine devam eder.

            ArrayList liste = new ArrayList();
            liste.Add(1);
            liste.Add(2);
            liste.Add(3);
            liste.Remove(3);
//liste ArrayListine eklenen object tipli "3" verisi silinecektir.

Dikkat!!!:Remove() metodu, koleksiyondaki elemanı siliyor ama elemana ayrılan alanı silmiyor.O alana Null değerini koyuyor.
Capacity Özelliği
Capacity özelliği ile ArrayList’in içine konulacak MAX eleman sayısını görebiliriz.(Tabi o MAX eleman sayısı geçildiği anda otomatik olarak artacaktır.)
TrimToSize Metodu
ArrayList in Capacity sindeki boş bulunan alanları bellekten atar.Aşağıdaki örneği inceleyiniz.

            ArrayList liste = new ArrayList();
            liste.Add(1);
            liste.Add(2);
            liste.Add(3);
            liste.Add(4);
            liste.Add(5);
            liste.Add(6);
            liste.Add(7);
            liste.Add(8);
            liste.Add(9);
            MessageBox.Show("Kapasite : " + liste.Capacity);
//Kodları buraya kadar derleyip çalıştırırsak kapasitenin 16 olduğunu görürüz.
            liste.TrimToSize();
            MessageBox.Show("Kapasite : " + liste.Capacity);
//Son iki satırdaki kodlarla beraber çalıştırılırsa eğer kapasitenin 9 olduğunu göreceksiniz.

Yukarıda gördüğünüz örnekte, kapasitesi 16 olan ArrayList’e TrimToSize() metodu uygulanıp boş alanlar siliniyor ve kapasitesi 9 a indiriliyor.Bu işlem sonucunda bellekten tasarruf sağlanmış olunuyor.
Clear Metodu
Clear() metodu sayesinde ArrayList’teki elemanların hepsi silinecektir.Ancak Remove() metodunda olduğu gibi elemanların alanları silinmeyecektir.Şimdi aşağıdaki örneği inceleyiniz.

            ArrayList liste = new ArrayList();
            liste.Add(1);
            liste.Add(2);
            liste.Add(3);
            liste.Add(4);
            liste.Add(5);
            liste.Add(6);
            liste.Add(7);
            liste.Add(8);
            liste.Add(9);
            liste.Clear();
            MessageBox.Show(liste.Capacity.ToString());

Yukarıdaki liste adındaki ArrayList’imizin kapasitesi 16 dır.Clear() metodu uygulandığı halde mesaj kutusunda kapasiteyi 16 olarak göstermektedir.Demek ki, elemanların alanları silinmiyor.
Contains Metodu
Contains ile koleksiyon içinde belirlenen eleman var mı? yok mu? bakılır.

            ArrayList liste = new ArrayList();
            liste.Add(1);
            liste.Add(2);
            liste.Add(3);
            MessageBox.Show(liste.Contains(3).ToString());

Yukarıdaki kodu derleyip çalıştırırsanız True değerini verecektir.
Insert Metodu
Belirtilen indekse, belirtilen eleman eklenir.Aşağıdaki kodu inceleyiniz.

            ArrayList liste = new ArrayList();
            liste.Add(1);
            liste.Add(2);
            liste.Add(3);
            liste.Add(4);
            liste.Add(5);
            MessageBox.Show(liste[2].ToString());
            liste.Insert(2, 33);
            MessageBox.Show(liste[2].ToString());

Yukarıdaki kodu incelerseniz,ilk başta mesaj kutusunda 3 değerini yazacaktır.Insert() metoduyla, 2. indekse 33 değerini yazdırıyorum.Son olarak mesaj kutusunda 33 değerini yazacaktır..2. indexten itibaren diğer elemanlar bir sonraki indexe kayacaktırlar.
CopyTo Metodu
Bir ArrayList koleksiyonunu, bir diziye kopyalamamıza yarar.

            ArrayList liste = new ArrayList();
            liste.Add(1);
            liste.Add(2);
            liste.Add(3);
            liste.Add(4);
            liste.Add(5);
            int[] sayilar = new int[liste.Count];
            liste.CopyTo(sayilar);
            for (int i = 0; i < sayilar.Length; i++)
            {
                MessageBox.Show(sayilar[i].ToString());
            }

Yukarıdaki kodları incelerseniz,liste ArrayListini, sayilar dizisine kopyalayacaktır.
Sort Metodu
Bu metod koleksiyonumuzdaki elemanları sıralamamıza yarayacaktır.Bu şekilde kullanırsak int tiplerde küçükten büyüğe doğru,stringlerden alfabetik olarak sıralayacaktır.

            ArrayList liste = new ArrayList();
            liste.Add(123);
            liste.Add(24);
            liste.Add(453);
            liste.Add(2);
            liste.Add(34);
            liste.Sort();
            for (int i = 0; i < liste.Count; i++)
            {
                MessageBox.Show(liste[i].ToString());
            }

Hashtable
Dictionary tipinden bir koleksiyondur.Non-Generic tir.Key – Value çiftleri halinde bilgiler koleksiyonun elemanlarında saklanabilir.

            Hashtable liste = new Hashtable();
            liste.Add("Adı", "Gençay");
            liste.Add("Soyadı","Yıldız");
            liste.Add("Meslegi","Yazılım Uzmanı");

Yukarıda gördüğünüz gibi Key – Value ikilisi halinde bilgileri tutabiliyor.

            MessageBox.Show(liste["Adı"].ToString());
//"Gençay" yazacaktır.
            MessageBox.Show(liste["Soyadı"].ToString());
//"Yıldız" yazacaktır.
            MessageBox.Show(liste["Meslegi"].ToString());
//"Yazılım Uzmanı" yazacaktır.

Verilen Key değeri karşılığında Value değerini object tipte geri gönderir.

Hash : Bellek adresi demektir.
Hastable koleksiyonu elemanları içinde tutarken bellekte yerleştirdiği Hash Code a göre tutar.Böylece biz Hashtable’a eklediğimiz ilk elemanı,ilk sırada tutacağını varsayamayız.Elemanlar belleğin boş kısımlarına yerleşir, bellek adresleri yani Hashleri koleksiyon içinde tutulur.Bundan dolayı koleksiyona eklediğimiz sırada elemanları elde etmemiz mümkün olmaz.Bundan dolayıda Hashtable koleksiyonlar üzerinde Sort(sıralama) işlemi yapılmaz.

            foreach (string item in liste.Keys)
            {
                MessageBox.Show(item);
            }
//.Keys ile keylere,
            foreach (string item in liste.Values)
            {
                MessageBox.Show(item);
            }
//.Values ile valuelere ulaşılabilir.

SortedList
Aynı Hashtable gibidir.Hastable elemanları hashlere göre yerleştirirken, SortedList sıralı olarak yerleştirir.Böylece SortedList içindeki elemanlara sıradan erişmek mümkün olur.

            SortedList slist = new SortedList();
            slist.Add("Adı", "Gençay");
            slist.Add("Soyadi", "Yıldız");
            slist.Add("Yaşı", 21);
            slist.Add("Doğum Yılı", 1992);

Hashtable, SortedList’ten daha hızlı çalışıyor.

Şimdilik bu kadar..
Bir sonraki yazımda görüşmek üzere..
İyi çalışmalar.

Mobil sürümden çık