C Sharp Programlama Dili/Koleksiyonlar
Koleksiyonlar nesneleri gruplamaya yarayan sınıflardır. Yani bir koleksiyon nesnesi birden fazla nesneyi temsil eder. .Net Framework kütüphanesindeki koleksiyon sınıfları System.Collections isim alanındadır. Koleksiyonlarla diziler arasında şu farklar vardır:
- Diziler System.Array türünden birer nesnedir.
- Koleksiyonlar ise System.Collections isim alanındaki çeşitli sınıflar türünden birer nesnedir.
- Koleksiyonlar dizilere göre bize daha fazla özgürlük verir. Çünkü koleksiyonlar içinde her türden nesne tutabiliriz. Ayrıca koleksiyonların boyutu sabit değildir. Eleman eklendikçe boyut dinamik olarak artar. Koleksiyonlar bize bunun gibi benzer avantajlar da verir. Konuyu işledikçe bu avantajları göreceksiniz.
Koleksiyon sınıflarının tamamı IEnumerable arayüzünü uygulamıştır. Dolayısıyla tüm koleksiyon nesneleri foreach döngüsüyle kullanılabilir. Ayrıca bunun haricinde her koleksiyon sınıfı kendine özgü birtakım arayüzleri de uygulamış olabilir. Örneğin birazdan göreceğimiz ArrayList sınıfı IList ve ICollection arayüzlerini de uygulamıştır. Bu arayüzlerin her birinin farklı anlamları vardır. Şimdi bu arayüzleri görelim:
ICollection Bu arayüz bir koleksiyonda bulunabilecek en temel üye elemanları içerir. System.Collections isim alanındaki bütün koleksiyon sınıfları bu arayüzü uygulamıştır. ICollection arayüzü IEnumerable arayüzünden türemiştir. Dolayısıyla ICollection arayüzünü uygulayan bir sınıf IEnumerable arayüzünü de uygulamış demektir.
IComparer Bu arayüz iki nesnenin karşılaştırılabilmesini sağlayan Compare() metodunu içerir. Bu metot iki nesnenin nasıl karşılaştırılacağını belirler. Compare() metodunun prototipi şu şekildedir:
int Compare(object o1,object o2)
Compare metodu -1, 0 ya da 1 değeri döndürür. Karşılaştırma genellikle büyüklük-küçüklük ilişkisine göre yapılır.
IDictionary Bu arayüzü anahtar-kilit ilişkisini uygulayan koleksiyon sınıfları uygular. Anahtar-kilit ilişkisini daha sonra göreceğiz. IDictionary arayüzü ICollection arayüzünden türemiştir.
IDictionaryEnumerator IDictionary arayüzünün özelleşmiş bir şeklidir. İleride göreceğiz.
IEnumerable İlgili koleksiyon nesnesinin foreach döngüsüyle kullanılabilmesini sağlayan arayüzdür.
IEnumerator IEnumerable arayüzüyle son derece ilişkilidir. IEnumerable arayüzü IEnumerator arayüzünün kullanılmasını zorlar. Aslında foreach döngüsünün kurulabilmesi için gerekli üye elemanlar IEnumerator arayüzündedir. IEnumerable arayüzü sadece IEnumerator arayüzünü zorlamak için aracı vazifesi görür.
IList Koleksiyon nesnelerine bir indeks numarasıyla erişilebilmesini sağlayan arayüzdür. IList ICollection arayüzünden türemiştir.
IHashProvider İleride göreceğimiz Hashtable koleksiyon sınıfıyla ilgilidir. System.Collections isim alanındaki arayüzlerden sonra artık aynı isim alanındaki koleksiyon sınıflarına geçebiliriz. Bunlar ArrayList, Hashtable, SortedList, BitArray, Stack ve Queue sınıflarıdır. Şimdi bu sınıfları teker teker inceleyelim.
ArrayList sınıfı
değiştirKoleksiyon sınıflarının en genel amaçlı olanıdır. Dizilere oldukça benzer. Dizilerden tek farkı eleman sayısının sabit olmaması ve yalnızca object tipinden nesneleri saklamasıdır. ArrayList sınıfı ICollection, IEnumerable, IList ve ICloneable arayüzlerini uygular. ArrayList sınıfının aşırı yüklenmiş üç tane yapıcı metodu vardır. Bunlar:
ArrayList al=new ArrayList();
Bu şekilde kapasitesi olmayan bir ArrayList nesnesi oluşturulur. Tabii ki koleksiyona yeni nesneler eklendikçe bu kapasite dinamik olarak artacaktır.
ArrayList al=new ArrayList(50);
Bu şekilde 50 kapasiteli bir ArrayList nesnesi oluşturulur. Yine kapasite aşılırsa dinamik olarak artırılır.
ArrayList al=new ArrayList(ICollection ic);
Burada ICollection arayüzünü uygulamış herhangi bir sınıf nesnesi parametre olarak verilir.
Daha önceden dediğim gibi ArrayList sınıfı nesneleri object olarak tutar. Yani bu koleksiyondan nesneleri elde ettiğimizde object hâldedirler. Genellikle bu nesneleri kullanabilmek için orijinal türe tür dönüşüm operatörüyle dönüşüm yapmak gerekir. Bir ArrayList nesnesine nesne eklemek için Add() metodu kullanılır. Bu metot parametre olarak object nesnesi alır ve bu nesneyi koleksiyonun sonuna ekler. Aynı şekilde bir ArrayList koleksiyonundan eleman çıkarmak için Remove() metodu kullanılır. Parametre olarak verilen object nesnesi koleksiyondan çıkarılır. Eğer nesne bulunamazsa hata oluşmaz, program işleyişine devam eder. Ayrıca herhangi bir ArrayList koleksiyonunun kapasitesini öğrenmek için ArrayList sınıfının Capacity özelliği kullanılır. Şimdi bütün bu üye elemanları bir örnek üzerinde görelim:
using System;
using System.Collections;
class Koleksiyonlar
{
static void Main()
{
ArrayList al=new ArrayList();
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add(5);
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add("Deneme");
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add('D');
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add(1.2f);
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add(3.4);
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add(1.2m);
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add("Vikikitap");
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add('e');
Console.WriteLine("Kapasite: "+al.Capacity);
al.Add(2);
Console.WriteLine("Kapasite: "+al.Capacity);
EkranaYaz(al);
al.Remove("Deneme");
Console.WriteLine("Kapasite: "+al.Capacity);
EkranaYaz(al);
}
static void EkranaYaz(ArrayList al)
{
foreach(object o in al)
Console.Write(o.ToString()+" ");
Console.WriteLine();
}
}
Bu programın ekran çıktısı şöyle olmalıdır:
Kapasite: 0 Kapasite: 4 Kapasite: 4 Kapasite: 4 Kapasite: 4 Kapasite: 8 Kapasite: 8 Kapasite: 8 Kapasite: 8 Kapasite: 16 5 Deneme D 1,2 3,4 1,2 Vikikitap e 2 Kapasite: 16 5 D 1,2 3,4 1,2 Vikikitap e 2
Bu ekran çıktısından şunları anlıyoruz:
- Kapasite başta 0, sonra 4, sonra da gerekli olduğunda kapasite ikişer kat artırılıyor.
- Remove() metoduyla koleksiyonunun elemanını silmek kapasiteyi değiştirmiyor. Yani Remove() metoduyla yapılan şey koleksiyondan bir nesne silip onun yerine sona bir null eklemek.
NOT: C#'ta geçersiz türler arasında dönüşüm yapmak yasaktır. Örneğin bir object nesnesinin gizli türü string değilse bunu
string s=(string)o;
şeklinde stringe çeviremeyiz. Bir ArrayList koleksiyonuna nesne yerleştirmek (araya sıkıştırmak) için Insert metodu kullanılır. Prototipi şu şekildedir:
void Insert(int indeks,object deger)
Bu metotla ilgili koleksiyonun indeks nolu elemanına deger koyulur. Bu indeksteki önceki eleman ve bu indeksten sonraki elemanlar ileriye bir birim ötelenir. Bildiğimiz üzere bu normal dizilerde mümkün değildi. Sabit kapasiteli ArrayList koleksiyonu oluşturmak içinse ArrayList sınıfının static FixedSize metodu kullanılır. Örnek:
ArrayList al=ArrayList.FixedSize(ArrayList koleksiyon);
Yani burada önceden tanımlanmış bir ArrayList nesnesi başka bir ArrayList nesnesine sabit kapasiteli olarak atanıyor. Eğer al koleksiyonunun kapasitesi aşılırsa tıpkı dizilerdeki gibi istisnai durum meydana gelir.
NOT: ArrayList koleksiyonunun elemanlarına tıpkı dizilerdeki gibi indeksleyici ile de erişilebilir.
Şimdi istersek ArrayList sınıfının diğer önemli üye elemanlarına bir göz atalım. Önce özellikler:
Count İlgili ArrayList nesnesindeki toplam eleman sayısını verir. Capacity özelliği ile karıştırılmamalıdır. Count özelliği "doldurulmuş" eleman sayısını verir. Geri dönüş tipi inttir.
IsFixedSize İlgili ArrayList nesnesinin sabit kapasiteli olup olmadığını verir. Eğer sabit kapasiteli ise true, değilse false değer döndürür.
IsReadOnly İlgili ArrayList nesnesinin salt okunur olup olmadığını verir. Eğer salt-okunur ise true, değilse false değer döndürür. Salt-okunur ArrayList nesneleri elde etmek için ArrayList sınıfının static ReadOnly() metodu kullanılır. Kullanımı FixedSize() metodu ile aynıdır. Sıra geldi metotlara:
AddRange(ICollection ic) Bu metot ile parametredeki koleksiyonun tüm elemanları ilgili koleksiyonun sonuna eklenir. Parametrenin ICollection tipinden olması demek bu sınıfın ICollection arayüzünü uygulaması gerekliliğini belirtir. Bildiğiniz gibi System.Generic isim alanındaki bütün koleksiyonlar ICollection arayüzünü uygulamıştır.
Sort() Koleksiyonları sıralamak için kullanılır. Eğer koleksiyon salt-okunur ise istisnai durum oluşur. Üç farklı aşırı yüklenmiş hâli vardır:
- void Sort() İlgili koleksiyonu ilgili koleksiyonun Compare() metodu kullanarak sıralar. Tabii ki ilgili koleksiyon IComparer arayüzünü uygulamalıdır.
- void Sort(IComparer ic) IComparer arayüzünü uygulayan başka bir sınıfın Compare() metodu kullanılarak sıralama yapılır.
- void Sort(int indeks,int adet,IComparer ic) Üsttekinden tek farkı bunda sadece indeksten itibaren adet kadar elemanın sıralanmasıdır.
int BinarySearch(object o) Sıralanmış koleksiyonlarda arama yapılır. Eğer o nesnesi bulunursa bulunulan indeksle geri dönülür, bulunamazsa negatif bir sayıyla geri dönülür. Bu metodun aşağıdaki gibi iki versiyonu daha vardır:
- int BinarySearch(object o,IComparer ic) Arama için başka bir sınıfın Compare() metodu kullanılır. Bu metot daha çok kullanıcının tanımladığı türden nesneler içeren koleksiyonlarda arama yapmak için kullanılır.
- int BinarySearch(int indeks,int adet,object o,IComparer ic) Üstekinden tek farkı indeksten itibaren adet kadar eleman içinde arama yapılmasıdır.
void Reverse() İlgili koleksiyon ters çevrilir. Başka bir kullanımı daha vardır.
- void Reverse(int indeks,int adet) Ters çevirme işlemi yalnızca indeksten itibaren adet kadar elemana uygulanır.
void Clear() İlgili koleksiyonun tüm elemanları temizlenir. Dolayısıyla Count özelliği sıfırlanırken Capacity özelliğinin değeri değişmez.
void TrimToSize() Koleksiyonun kapasitesi eleman sayısından fazla olduğu durumlarda gereksiz kısımlar silinir. Dolayısıyla kapasiteyle eleman sayısı eşitlenir.
bool Contains(object o) Parametre ile verilen nesnenin ilgili koleksiyonda bulunup bulunmadığı kontrol edilir. Eğer varsa true, yoksa false değer döndürür.
void CopyTo() ArrayList nesnesindeki elemanları normal tek boyutlu dizilere (System.Array) kopyalamak için kullanılır. Üç farklı kullanımı vardır:
- void CopyTo(Array a) Metodu çağıran ArrayList nesnesindeki tüm elemanlar a dizisine ilk indeksten itibaren kopyalanır.
- void CopyTo(Array a,int indeks) Üsttekiyle aynı göreve sahiptir. Tek farkı kopyalamanın indeks. elemandan itibaren yapılmasıdır.
- void CopyTo(int indeks,Array a,int dizi_indeks,int adet) Metodu çağıran ArrayList nesnesindeki indeksten itibaren adet kadar eleman a dizisinde dizi_indeks indeksli eleman ve sonrasına kopyalanır.
ArrayList GetRange(int indeks,int adet) Metodu çağıran ArrayList nesnesinin indeks nolu elemanından itibaren adet kadar elemanı yeni bir ArrayList nesnesi olarak tutulur.
int IndexOf(object o) Parametre olarak verilen o nesnesinin ilgili ArrayList nesnesinde ilk bulunduğu indeksi döndürür. Object nesnesi bulunamazsa negatif değer döndürülür.
object[] ToArray() İlgili ArrayList nesnesindeki elemanları bir object dizisi olarak tutar. Farklı bir versiyonu daha vardır:
- Array ToArray(Type t) İlgili ArrayList nesnesindeki elemanları t türünden bir dizi olarak tutar. Yani gerekli tür dönüşüm işlemleri otomatik olarak yapılır.
void RemoveAt(int indeks) İlgili ArrayList nesnesindeki indeks nolu elemanı siler. Belirtilen indeks 0'dan küçük ya da koleksiyonun Count değerinden büyükse istisnai durum oluşur.
Hashtable sınıfı
değiştirArray ve ArrayList sınıflarında dizideki elemanlara belirli bir indeks numarası ile erişiriz. Ancak bu bazen uygun yöntem olmayabilir. Çünkü hangi nesnenin hangi indekse karşılık geldiğini bilmemiz gerekir. Halbuki System.Collections isim alanındaki Hashtable sınıfında koleksiyonumuzun her nesnesine istediğimiz bir ismi verip koleksiyonumuzun elemanlarına bu isimlerle erişebiliriz. Bunun diğer adı anahtar-değer ilişkisidir. Yani bir anahtarla yalnızca bir nesneyi ifade ederiz. Örnek:
Hashtable h=new Hashtable();
h.Add("Anahtar1","Değer1");
h.Add("Anahtar2","Değer2");
Gördüğünüz gibi her Hashtable nesnesinin iki kısmı var. Bunlardan birisi ilgili nesnenin ismi (anahtar) ötekisi de nesnenin kendisi (değer). Bu ikisinin tipi string olmak zorunda değildir. istenilen tür olabilir. İlgili Hashtable nesnesine eleman eklerken Add() metodunda ilk parametre anahtar, ikinci parametre değerdir. Hashtable nesnesine yukarıdakinin yanı sıra aşağıdaki gibi de eleman ekleyebiliriz:
h["Anahtar1"]="Değer1";
h["Anahtar2"]="Değer2";
İstersek daha sonra Hashtable nesnesindeki anahtarların değerlerini değiştirebiliriz. Örnek:
h["Anahtar1"]="Yeni Değer";
Burada Anahtar1'in değerini değiştirdik. Add() metoduyla var olan bir anahtarı eklemeye çalışmak istisnai durum oluşmasına neden olur. Hashtable sınıfının Count özelliği ilgili Hashtable nesnesindeki anahtar-değer çifti sayısını döndürür. Ayrıca bir Hashtable nesnesindeki tüm anahtarları elde etmek için Keys özelliği kullanılır. Bu özellik ilgili Hashtable nesnesindeki tüm anahtarları bir ICollection nesnesi (bir koleksiyon) olarak döndürür. Values özelliği ise aynı şeyi değerler için yapar. Örnek program:
using System;
using System.Collections;
class hashtable
{
static void Main()
{
Hashtable Sozluk=new Hashtable();
Sozluk.Add("araba","car");
Sozluk["kitap"]="book";
ICollection anahtarlar=Sozluk.Keys;
foreach(string s in anahtarlar)
Console.WriteLine(s);
ICollection degerler=Sozluk.Values;
foreach(string s in degerler)
Console.WriteLine(s);
Console.WriteLine("Toplam kelime: "+Sozluk.Count);
}
}
Bu programın çıktısı şu şekildedir:
kitap araba book car Toplam kelime: 2
Bu programı şöyle de yazabiliriz:
using System;
using System.Collections;
class hashtable
{
static void Main()
{
Hashtable Sozluk=new Hashtable();
Sozluk.Add("araba","car");
Sozluk["kitap"]="book";
IDictionaryEnumerator ide=Sozluk.GetEnumerator();
while(ide.MoveNext())
Console.WriteLine(ide.Key+" = "+ide.Value);
Console.WriteLine("Toplam kelime: "+Sozluk.Count);
}
}
Yani Hashtable sınıfının static olmayan GetEnumerator() metodu IDictionaryEnumerator arayüzü türünden bir nesne döndürüyor. Bu nesne üzerinden MoveNext() metoduna erişiyoruz. MoveNext() metodu ilgili IDictionaryEnumerator nesnesinin temsil ettiği anahtar-değer çiftini bir öteleyip true döndürüyor. Eğer öteleyemiyorsa false döndürüyor. Bir Hashtable nesnesinden bir anahtar-değer çiftini silmek için Hashtable sınıfının Remove() metodu kullanılır. Parametre olarak anahtarı alır. Örnek:
Sozluk.Remove("araba");
Bu satır Sozluk koleksiyonundaki "araba" anahtarını ve buna karşılık gelen değeri silecektir. Eğer ilgili koleksiyon salt-okunur ise, sabit kapasiteli ise, belirtilen anahtar yok ya da değeri null ise istisnai durum oluşur. IsReadOnly ve IsFixedSize özellikleri Hashtable sınıfında da bulunmaktadır. Hashtable sınıfının diğer önemli metotları:
void Clear() İlgili Hashtable nesnesindeki tüm anahtar-değer çiftlerini siler. Dolayısıyla Hashtable nesnesinin Count özelliğinin değeri 0 olur.
bool ContainsKey(object anahtar) Parametre ile verilen anahtar ilgili Hashtable nesnesinde varsa true, yoksa false değer döndürür. Aynı sınıftaki Contains() metodu da aynı işleve sahiptir.
bool ContainsValue(object deger) Parametre ile verilen değer ilgili Hashtable nesnesinde varsa true, yoksa false değer döndürür.
void CopyTo(Array dizi,int indeks) İlgili Hashtable nesnesindeki anahtar-değer çiftlerini bir boyutlu Array dizisine indeks indeksinden itibaren kopyalar. Kopyalama işleminin yapıldığı dizi DictionaryEntry yapısı türündendir. Bu yapıdaki Key ve Value özellikleri ilgili Hashtable nesnesindeki anahtar ve değerleri tutar. İlgili Hashtable nesnesindeki sadece anahtarları bir diziye kopyalamak için;
hashtable.Keys.CopyTo(dizi,indeks);
Aynı işlemi sadece değerler için yapmak içinse;
hashtable.Values.CopyTo(dizi,indeks);
SortedList sınıfı
değiştirSortedList koleksiyonunda elemanlara hem anahtar-değer çiftli hem de ArrayList sınıfında olduğu gibi indeksli olarak erişebiliriz. Ancak SortedList sınıfının önceki gördüğümüz iki sınıftan en büyük farkı elemanların daima sıralı olmasıdır. Çeşitli şekillerde SortedList nesneleri oluşturulabilir:
SortedList sl1=new SortedList();
SortedList sl2=new SortedList(50);
SortedList sl3=new SortedList(IDictionary id);
Birincisinde henüz kapasitesi olmayan bir SortedList nesnesi oluşturulur. İkincisinde başlangıç kapasitesi 50 olan bir SortedList nesnesi oluşturulur. Üçüncüsünde ise IDictionary arayüzünü uygulamış olan bir sınıfın nesnesi parametre olarak alınır ve bu sınıfın (koleksiyonun) elemanlarından SortedList nesnesi oluşturulur. Daha önce gördüğümüz Hashtable sınıfı IDictionary arayüzünü uygulamıştır. Üçünde de kapasite aşılırsa otomatik olarak kapasite artırılır. SortedList sınıfında Hashtable sınıfındaki Add(), Clear(), Contains(), ContainsKey(), ContainsValue(), GetEnumerator() ve Remove() metotları bulunur. Kendine özgü metotları ise
object GetByIndex(int indeks) İlgili SortedList nesnesindeki indeks nolu anahtar-değer çiftinin değer kısmı döndürülür.
object GetKey(int indeks) İlgili SortedList nesnesindeki indeks nolu anahtar-değer çiftinin anahtar kısmı döndürülür.
IList GetKeyList() İlgili SortedList nesnesindeki anahtarlar IList arayüzü türünden döndürülür.
IList GetValueList() İlgili SortedList nesnesindeki değerler IList arayüzü türünden döndürülür.
int IndexOfKey(object anahtar) İlgili SortedList nesnesindeki parametrede verilen anahtarın hangi indekste olduğu döndürülür. Anahtar bulunamazsa negatif değer döndürülür.
int IndexOfValue(object deger) Yukarıdaki şeyi değerler için yapar.
void SetByIndex(int indeks,object deger) İlgili SortedList nesnesindeki indeks nolu elemanın değeri deger olarak değiştirilir. Anahtarda değişme olmaz.
void TrimToSize() İlgili SortedList nesnesinin kapasitesi eleman sayısına eşitlenir. SortedList sınıfının özellikleri ise Capacity, Count, IsFixed, IsReadOnly, Keys ve Values'dir. Keys ve Values özellikleri ile Hashtable sınıfında olduğu gibi ICollection nesnesi elde edilir. İlgili SortedList nesnesindeki elemanlara erişmek için Keys ve Values özellikleri kullanılabileceği gibi DictionaryEntry yapısı da kullanılabilir. Bu yapı ilgili koleksiyondaki değer ve anahtarları temsil eden özellikler içerir. Örneğe geçmeden önce SortedList sınıfının sıralamayı nasıl yaptığını söylemek istiyorum:
Herhangi bir SortedList nesnesiyle her işlem yapıldıktan sonra ilgili koleksiyon sıralanır. Sıralama anahtarlara göredir. Dolayısıyla biz anahtarların sırasını değiştiremeyiz. Şimdi SortedList sınıfıyla ilgili bir örnek yapalım:
using System;
using System.Collections;
class sortedlist
{
static void Main()
{
string[] kelimeler={"araba","masa","defter","kitap","okul"};
SortedList sozluk=new SortedList();
sozluk.Add("araba","car");
sozluk.Add("masa","table");
sozluk.Add("kalem","pencil");
sozluk["kitap"]="book";
sozluk["bilgisayar"]="computer";
EkranaYaz(sozluk);
for(int i=0;i<kelimeler.Length;i++)
if(sozluk.ContainsKey(kelimeler[i]))
Console.WriteLine(kelimeler[i]+"="+sozluk[kelimeler[i]]);
else
Console.WriteLine(kelimeler[i]+" sözlükte bulunamadı.");
Console.WriteLine();
sozluk.Add("doğru","line");
EkranaYaz(sozluk);
Console.WriteLine();
Console.WriteLine("Sıralı listede toplam {0} eleman bulunmaktadır.",sozluk.Count);
Console.WriteLine("Bu elemanlar: ");
ICollection anahtarlar=sozluk.Keys;
foreach(string s in anahtarlar)
Console.Write(s+"-");
}
static void EkranaYaz(SortedList sl)
{
foreach(DictionaryEntry de in sl)
Console.WriteLine("{0,-12}:{1,-12}",de.Key,de.Value);
Console.WriteLine();
}
}
BitArray sınıfı
değiştirBitArray içinde yalnızca bool türünden nesneler saklayabilen bir koleksiyondur. Bir BitArray nesnesi şu yollarla oluşturulabilir.
BitArray ba1=new BitArray(BitArray ba2);
BitArray ba2=new BitArray(bool[] b);
BitArray ba3=new BitArray(byte[] by);
BitArray ba4=new BitArray(int[] i);
BitArray ba5=new BitArray(int boyut);
BitArray ba6=new BitArray(int boyut,bool deger);
Birincisinde başka bir BitArray nesnesinden yeni bir BitArray nesnesi oluşturulur. Yani tabiri caizse kopyalama işlemi yapılmış olur. İkincisinde bir bool dizisinden yeni bir BitArray nesnesi oluşturulur.
Üçüncüsünde bir byte dizisinden yeni bir BitArray nesnesi oluşturulur. Bir bayt 8 bittir. Yani bir baytın içinde 8 tane 1 veya 0 vardır. İşte bu 1 veya 0'lar BitArray koleksiyonuna true ve false olarak geçirilir. Yani son tahlilde BitArray dizisindeki eleman sayısı 8*by.length olur.
Dördüncüsünde bir int dizisinden yeni bir BitArray nesnesi oluşturulur. Bir int nesnesinin içinde 32 tane 1 veya 0 vardır. Çünk int 32 bitlik bir veri tipidir. Bu 1 veya 0'lar BitArray koleksiyonuna true veya false olarak geçirilir. Yani son tahlilde BitArray dizisindeki eleman sayısı 32*i.Length olur.
Beşincisinde boyut tane false eleman içeren bir BitArray nesnesi oluşturulur. Altıncısında boyut tane degerden oluşan bir BitArray nesnesi oluşturulur.
BitArray sınıfı ICollection ve IEnumerable arayüzlerini uygulamıştır. Örnek bir program:
using System;
using System.Collections;
class bitarray
{
static void Main()
{
int[] i={1};
BitArray ba=new BitArray(i);
EkranaYaz(ba);
}
static void EkranaYaz(BitArray ba)
{
IEnumerator ie=ba.GetEnumerator();
int i=0;
while(ie.MoveNext())
{
i++;
Console.Write("{0,-6}",ie.Current);
if(i%8==0)
Console.WriteLine();
}
Console.WriteLine();
}
}
Bu programın ekran çıktısı şöyle olmalıdır:
True False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False
Bu programda ba'yı ekrana klasik foreach ile de yazdırabilirdik. Ancak böyle bir yöntemin de olduğunu bilmenizde fayda var.
BitArray sınıfının Count ve Length adlı iki özelliği vardır. İkisi de ilgili BitArray nesnesinin eleman sayısını verir. Ancak Count salt-okunur olmasına rağmen Length değildir. Yani Length özelliği ile ilgili BitArray nesnesinin eleman sayısını değiştirebiliriz. Eğer var olan eleman sayısını azaltırsak sonundan gerekli sayıda eleman silinecektir. Eğer eleman sayısını artırısak sona gerekli sayıda false eleman eklenir. BitArray sınıfının önemli metotları:
bool Get(int indeks) İlgili BitArray nesnesindeki parametre ile verilen indeksteki eleman geri döndürülür.
void Set(int indeks,bool deger) İlgili BitArray nesnesindeki parametre ile verilen indeksteki eleman deger olarak değiştirilir.
void SetAll(bool deger) İlgili BitArray nesnesindeki tüm elemanlar deger olarak değiştirilir.
BitArray And(BitArray ba) İlgili BitArray nesnesindeki elemanlarla parametredeki BitArray nesnesindeki elemanları karşılıklı olarak VE işlemine sokar. Sonucu yine bir BitArray nesnesi olarak tutar. Eğer iki nesnenin eleman sayıları eşit değilse istisnai durum oluşur.
BitArray Or(BitArray ba) And() metoduyla aynı mantıkta çalışır. Tek değişen elemanların VE değil de VEYA işlemine sokulmasıdır.
BitArray Xor(BitArray ba) And() ve Or() metotlarıyla aynı mantıkta çalışır. Tek değişen elemanların ÖZEL VEYA işlemine sokulmasıdır.
BitArray Not() İlgili BitArray nesnesindeki elemanların değilini alır ve yeni bir BitArray nesnesi olarak döndürür.
Stack sınıfı
değiştirSystem.Collections isim alanındaki Stack sınıfı bilgisayar bilimlerinde çokça karşımıza çıkabilecek yığınlarla çalışmamızı sağlar. Yığınları üst üste koyulmuş kitaplar gibi düşünebiliriz. En üstteki kitabı rahatlıkla alıp okuyabiliriz. Ancak okuyacağımız kitap ortalarda veya altlarda ise önce okuyacağımız kitabın üstündeki kitapları teker teker yığından çıkarıp sonra okuyacağımız kitabı almalıyız. Öbür türlü kitap destesi devrilebilir. İşte yığınlarda da aynı mantık söz konusudur. Yığınlara koleksiyonlara bu mantığın eklenmiş hâlidir diyebiliriz. Normal koleksiyonlarda istediğimiz her an koleksiyonun istediğimiz elemanına erişebiliyorduk. Ancak yığınlarda bir anda yığının yalnızca bir elemanına erişebiliriz. Daha alttaki elemanlara erişebilmek için üstteki elemanların teker teker yığından çıkarılması gerekir. Yığınların mantığını şu cümleyle özetleyebiliriz: "En önce giren en son çıkar, en son giren en önce çıkar." Yani yığına eklenen her bir elemanın birbirinin üstüne geldiğini söyleyebiliriz. Stack sınıfında tıpkı diğer koleksiyonlardaki gibi eleman eklendikçe otomatik olarak kapasite artar. Bir Stack nesnesi şu yollardan biriyle olışturulabilir.
Stack s1=new Stack();
Stack s2=new Stack(int kapasite);
Stack s3=new Stack(ICollection ic);
Birincisinde klasik bir Stack nesnesi oluşturulur. İkincisinde kapasitesi kapasite olan bir Stack nesnesi oluşturulur. Tabii ki kapasite aşılırsa otomatik olarak kapasite artırılır. Üçüncüsünde ICollection arayüzünü kullanan başka bir koleksiyon nesnesinden yeni bir Stack nesnesi oluşturulur. Stack sınıfının önemli üye elemanları:
object Pop() İlgili yığındaki en üstteki elemanı döndürür ve yığından çıkarır.
object Peek() İlgili yığındaki en üstteki elemanı döndürür ama yığından çıkarmaz.
void Push(object o) İlgili yığının en üstüne o elemanını ekler.
void Clear() İlgili yığındaki bütün elemanları siler.
object[] ToArray() İlgili yığındaki elemanlar object dizisi olarak döndürülür.
bool Contains(object o) Eğer o nesnesi ilgili yığında varsa true, yoksa false döndürülür.
int Count Bu özellik ilgili yığındaki eleman sayısını verir.
Peek() ve Pop() metotları ilgili yığın boşken kullanılırsa istisnai durum oluşur. Bir yığındaki elemanların tamamına bir koleksiyonmuş gibi erişmek için Stack sınıfının GetEnumerator() metodu kullanılır. Bu metot bir IEnumerator nesnesi döndürür. IEnumerator arayüzünün MoveNext() metoduyla bir while döngüsü kurarsak ilgili yığındaki tüm elemanlara erişebiliriz. Örnek:
using System;
using System.Collections;
class stack
{
static void Main()
{
Stack s=new Stack();
s.Push(5);
s.Push(10);
EkranaYaz(s);
}
static void EkranaYaz(Stack s)
{
IEnumerator ie=s.GetEnumerator();
while(ie.MoveNext())
Console.WriteLine(ie.Current);
}
}
Bu programdaki EkranaYaz() metodunu şöyle de yazabilirdik:
static void EkranaYaz(Stack s)
{
Stack yeniyigin=(Stack)s.Clone();
while(yeniyigin.Count>0)
Console.WriteLine(yeniyigin.Pop().ToString());
}
Buradaki Clone() metodu bir yığının kopyasını object olarak alır. Dolayısıyla bu yeni yığını bir Stack nesnesine atamak için tekrar Stack türüne dönüşüm yapmak gerekir. Yine EkranaYaz() metodunu klasik foreach döngüsüyle de yazabilirdik:
static void EkranaYaz(Stack s)
{
foreach(object o in s)
Console.WriteLine(o);
}
Queue sınıfı
değiştirQueue sınıfı Stack sınıfına oldukça benzer. Ancak Stack sınıfının tam tersi bir mantığa sahiptir. Queue sınıfında "En önce giren en erken çıkar, en son giren en geç çıkar." mantığı geçerlidir. Bunu şöyle kavrayabiliriz: Kendimizi bankada bir veznedar olarak düşünelim. Kuyrukta bekleyen birçok kişi var. Tabii ki kuyruktaki en öndeki kişinin işi en erken bitecek ve kuyruktan en önce o ayrılacaktır. Kuyruğun en arkasındaki kişinin işi ise en geç bitecektir. Bizim veznedar olarak en arkadaki kişinin işini halledebilmemiz için o kişinin önündeki kişilerin de işlerini bitirmemiz gerekir. Queue sınıfının önemli üye elemanları:
object Dequeue() İlgili kuyruğun en başındaki elemanı döndürür ve kuyruktan çıkarır.
void Enqueue(object o) o nesnesi ilgili kuyruğun en sonuna eklenir.
object Peek() İlgili kuyruğun en başındaki elemanı döndürür ama kuyruktan çıkarmaz.
int Count İlgili kuyruktaki eleman sayısını verir.
object[] ToArray() İlgili kuyruk bir object dizisi olarak tutulur.
void TrimToSize() İlgili kuyruğun kapasitesiyle eleman sayısı eşitlenir.
Yeni bir Queue nesnesi şöyle oluşturulabilir.
Queue q1=new Queue();
Queue q2=new Queue(int kapasite);
Queue q3=new Queue(ICollection ic);
Bir Queue nesnesinin içinde Stack nesnelerinin içinde dolaştığımız gibi dolaşabiliriz. Buna örnek verilmeyecektir.
Şablon tipli koleksiyonlar
değiştirŞimdiye kadar BitArray hariç bütün koleksiyon sınıflarında koleksiyona eklenen nesne objecte dönüştürülüp saklanır. Sonra bu nesneyi elde etmek istediğimizde ise tekrar orijinal türe dönüşüm yapmak gerekir. Bunun sonucunda hem performans kaybı (tür dönüşümlerinden dolayı) hem de tür emniyetsizliği oluşmaktadır. Tür emniyetsizliğinin nedeni ise ilgili koleksiyonda her türden veri saklayabilmemizdir. Sözlük için kullanacağımız bir koleksiyonun yalnızca string nesneleri kabul etmesi gerekir. Ancak klasik koleksiyonlarda her türden nesne atayabilmemiz bu kontrolü imkansız kılmaktadır. Şablon tipli koleksiyon sınıfları System.Collections.Generic isim alanındadır. Şimdiye kadar gördüğümüz bütün koleksiyonların şablon tipli versiyonları bu isim alanında bulunmaktadır. Şablon tipli koleksiyon sınıflarının karşılığı oldukları normal koleksiyon sınıflarından şablon tipli olmaları dışında fazla farkı yoktur. Burada bu şablon tipli koleksiyon sınıfları kısaca tanıtılacaktır.
List<T> sınıfı
değiştirArrayList sınıfının şablon tipli versiyonudur. Örnek bir List<T> nesnesi yaratımı:
List<int> l=new List<int>();
Dictionary<T,V> sınıfı
değiştirHashtable sınıfının şablon tipli versiyonudur. Örnek bir Dictionary<T,V> nesnesi yaratımı:
Dictionary<int,string> d=new Dictionary<int,string>();
SortedDictionary<K,V> sınıfı
değiştirSortedList sınıfının şablon tipli versiyonudur. Örnek bir SortedDictionary<K,V> nesnesi yaratımı:
SortedDictionary<int,string> sd=new SortedDictionary<int,string>();
IEnumerable<T> ve IEnumerator<T> arayüzleri
değiştirKlasik versiyonlarından türetilen bu arayüzler şablon tipli koleksiyon sınıflarına arayüzlük yapmaktadır. Kendimiz de şablon tipli koleksiyon sınıfları yazmak istiyorsak bu arayüzleri kullanmalıyız.
Queue<T> ve Stack<T> sınıfları
değiştirQueue ve Stack sınıflarını şablon tipli versiyonlarıdır.
Koleksiyonlara kendi nesnelerimizi yerleştirmek
değiştirŞimdiye kadar koleksiyonlara string, int gibi .Net Framework kütüphanesindeki hazır sınıfların nesnelerini koyduk. Halbuki kendi oluşturduğumuz sınıfların nesnelerini de koleksiyonlara koyabiliriz. Ancak bu durumda bir sorun ortaya çıkar. Derleyici koleksiyonu sıralarken nasıl sıralayacak? Bu sorunu çözmek için sınıfımıza IComparable arayüzünü uygulattırırız. Bu arayüz önceden de bildiğiniz gibi CompareTo() metodunu içermektedir. Şimdi programımızı yazmaya başlayalım:
using System;
using System.Collections;
class Sayi:IComparable
{
public int sayi;
public Sayi(int sayi)
{
this.sayi=sayi;
}
public int CompareTo(object o)
{
Sayi s=(Sayi)o;
return sayi.CompareTo(s.sayi);
}
}
class AnaProgram
{
static void Main()
{
ArrayList al=new ArrayList();
Sayi s1=new Sayi(10);
Sayi s2=new Sayi(20);
Sayi s3=new Sayi(-23);
al.Add(s1);
al.Add(s2);
al.Add(s3);
al.Sort();
foreach(Sayi s in al)
Console.WriteLine(s.sayi);
}
}