DİZİLER
Diziler için aynı tipteki verilerin tutulduğu bir koleksiyon diyebiliriz. Örneğin integer verinin bir yığın şeklinde tutulması için dizileri kullanırız. C# da diziler referans tipinde değişkenlerdendir. C# da tanımlanan tüm diziler System.Array sınıfından türemiş bir nesnedir.
Dizi tanımlama
<veri tipi>[] <değişken ismi> = new <veri tipi>[<dizinin boyutu>];
Tek bir tanımlama yapılarak istenilen sayıda veri girişi sağlanabilir. Dizi elamanları bir indis numarasına sahiptir. İndis numaraları varsayılan olarak sıfırdan başlar.
Ayrıca dizi tanımlaması yapıldığında dizinin eleman sayısı, kullanılacak eleman sayısından az ise dizi yeniden boyutlandırılabilir.
Dizi değişkeninin eleman sayısını belirtmek için new metodu kullanılır.
Bir dizinin boyutları sabittir ve kullanılmadan önce belirlenmelidir. Dizi boyutunu belirlemek için başka bir değişkende kullanabilirsiniz.
ÖRNEK:
int boyut = 10;
int[] integerDizi = new int[boyut];
Diziyi tanımlama ve başlangıç değerlerini atama işlemini ayrı satırlardada yapabilirsiniz.
int[] integerDizi;
integerDizi = new int[10];
Ayrıca dizileri tanımlarken dizi içine atmak istediğiniz verileride belirterek dizi tanımlayabilirsiniz. Bunun için kullanacağınız very tipine uygun olacak şekilde, süslü parantez içinde bir virgule ayrılmış dizi elemanlarını yazmanız yeterlidir.
int[] integerDizi = {1,2,3,4,5,6,7,8,9};
Dizi Elemanlarına Ulaşmak
Dizi elemanlarına ulaşmak için [indeks] indeks operatörünü kullanırız. Dikkat edilmesi gereken nokta C# da dizilerin elemanları 0. İndeksten başlar, yani eğer 5 elemanlı bir dizimiz varsa bu dizinin birinci elemanı 0. İndekste son elemanı ise 4. İndekstedir. 5 elemanlı bir dizinin 3.elemanına aşağıdaki gibi erişebiliriz.
int[] integerDizi = { 1, 2, 3, 4, 5};
int ucuncuEleman = integerDizi[2];
Bir dizi içindeki elemanlara ulaşmak için basit bir örnek:
int[] integerDizi = { 4, 8, 23, 64, 35 };
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Dizinin {0}. Elemanının Değeri = {1} ", i, integerDizi[i]);
}
Ekran görüntüsü
Bütün diziler System.Arry sınıfından türemiş nesnelerdir. System.Array sınıfının Length diye bir özelliği vardır. Bu nedenle tüm dizilerinde bir Length özelliği olur. Dizimizin eleman sayısını dizininAdi.Length diyerek alabiliriz.Yukarıdaki örneği bu yöntemle yeniden yazacak olursak;
int[] integerDizi = { 4, 8, 23, 64, 35 };
for (int i = 0; i < integerDizi.Length; i++)
{
Console.WriteLine("Dizinin {0}. Elemanının Değeri = {1} ", i, integerDizi[i]);
}
Yukarıdaki kodu çalıştırdığınızda bir önceki örneğimizle aynı sonucu üretir.
Örnek:
5 elemanlı bir küme dizisi tanımlanacak olursa;
İnt [] kume;
kume=new int[5]; komut satırları yazılarak tanımlama yapılmış olur.
Foreach Döngüsü
Diziler ve koleksiyonların elemanlarına erişmek için basit ve kullanışlı bir döngüdür. Foreach döngüsünün yapısı aşağıdaki gibidir
foreach(<dizi içindeki elemaların veri tipi> <değişken ismi> in <diziveyaKoleksiyonadi>)
{
<Kod blogumu>
}
Yukarıda for döngüsü ile yaptığımız örneğimiz foreach döngüsü ile yapalım.
foreach (int diziElemanı in integerDizi)
{
Console.WriteLine("Elemanın Değeri = {0} ", diziElemanı);
}
Foreach döngüsünü kullanırken ulaştığımız dizi elemanları readonly’ dir. Yani yukarıdaki örnek üzerinde gösterecek olursak foreach döngüsü içinde diziElamanlanı adlı integer değişkeninin içerdiği değeri değiştiremezsiniz. Eğer değiştirmeye kalkarsanız Cannot assign to ‘diziElemanı’ because it is a ‘foreach iteration variable’ hatasını alırsınız.
String tipindeki bir değişkende char tipindeki verilerin birleşmesinden oluşmuş bir dizidir. Öyleyse foreach döngüsü kullanarak aşağıdaki gibi bir stringin elemanlarına erişebiliriz.
string metin = "Yazılım Mutfağı";
foreach (char harf in metin)
{
Console.WriteLine("Harf = {0} ", harf);
}
Çok Boyutlu Diziler (Multidimensional Array)
Çok boyutlu bir dizi ‘dizinin dizisi’ şeklinde tabir edilebilir. Her elemanı başka bir dizi olan diziler çok boyutlu bir dizidir. Çok boyutlu bir dizi veritabanında her satırında birden fazla kolon bulunan bir tabloya benzetilebilir.
Eğer her satırda bulunan her kolon kendi içinde başka bir dizi barındırmıyorsa bu tür dizilere 2 boyutlu digger bir değişle çok boyutlu diziler denir.
Eğer her kolonda kendi içinde başka bir dizi barındırıyorsa bu tür dizelere n boyutlu diziler denir . Burda n ifadesi dizinin derinliğini ifade eder.
Çok boyutlu diziler iki çeşittir;
Düzenli Diziler: Her satırı aynı sayıda kolon barındıran diziler.
Düzensiz Diziler (Jagged Array) : Her satırı farklı sayıda kolon barındıran diziler.
Tek Boyutlu Diziler:
//Dizinin Oluşturulması
int[] intDizi = new int[5];
//Dizi elemanlarına değer ataması
intDizi[0] = 36; //dizinin ilk elemanına 36 değeri atandı
intDizi[2] = 26; //dizinin ikinci elemanına 26 değeri atandı
intDizi[4] = 32; //dizinin son elemanına 32 değeri atandı
Çok Boyutlu Diziler:
//Dizinin Oluşturulması
int[,] intCokBDizi = new int[2, 3];
//Dizi elemanlarına değer ataması
intCokBDizi[0, 0] = 23;
intCokBDizi[0, 1] = 25;
intCokBDizi[0, 2] = 33;
intCokBDizi[1, 0] = 41;
intCokBDizi[1, 1] = 29;
intCokBDizi[1, 2] = 93;
Çok Boyutlu Dizilerin Elemanlarına Döngü İle Ulaşmak
For Döngüsü
//Dizi elemanlarını for döngüsü ile bulmak.
for (int row = 0; row < intCokBDizi.GetLength(0); row++)
{
for (int col = 0; col < intCokBDizi.GetLength(1); col++)
{
Console.WriteLine("Dizinin {0},{1} indeksindeki değeri : {2}",row,col,intCokBDizi[row,col]);
}
}
Ekran Görüntüsü:
GetLength() fonksiyonu dizinin belirtilen boyutundaki eleman sayısını verir. Yukarıdaki örnekte görüldüğü gibi bir parameter olarak 0 veya yazıyoruz. 0 dizinin birinci boyutundaki eleman sayısı yani satır sayısı 1 verdiğimizde ise dizinin 2.boyutu yani kolon sayısını verir.
2 boyutlu düzensiz dizilerde foreach döngüsü kullanılmaz. Foreach döngüsünü sadece tüm elemanlara erişmek için kullanabiliriz. Eğer her boyuttaki elemana farklı erişmek istiyorsak for döngüsü kullanmamız gerekiyor. Foreach döngüsü ile düzensiz 2 boyutlu dizilerin elemanlarına erişebilir.
Düzensiz foreach döngüsü tanımlanması
//Dizinin Oluşturulması
int[][] intCokBDizi = new int[3][];
//İkinci boyutta bulunan her elemanda bir dizi olduğuna göre
//onlarıda new komutu ile ayarlamamız gerekir.
intCokBDizi[0] = new int[2];
intCokBDizi[1] = new int[4];
intCokBDizi[2] = new int[3];
//Dizi elemanlarına değer ataması
intCokBDizi[0][0] = 13;
intCokBDizi[0][1] = 15;
intCokBDizi[1][0] = 21;
intCokBDizi[1][1] = 29;
intCokBDizi[1][2] = 29;
intCokBDizi[1][3] = 23;
intCokBDizi[2][0] = 39;
intCokBDizi[2][1] = 39;
intCokBDizi[2][2] = 33;
Bir önceki anlattığımız düzensiz çok boyutlu dizide for döngüsü kullanarak elemanlara tek tek ulaşmıştık. Düzensiz dizilerde elemanlara tek tek ulaşmak istediğimizde for döngüsü yerine foreach döngüsü kullanıyoruz.
Foreach Döngüsü:
foreach (int[] row in intCokBDizi)
{
foreach (int col in row)
{
Console.WriteLine(col);
}
Console.WriteLine("---------");
}
Ekran Görüntüsü:
Yukarıda anlattıklarımızın ışığında 3 boyutlu düzenli ve düzensiz dizileri nasıl tanımlarız ve bunlara nasıl değer ataması yaparız bir örnekle anlatalım.
//3 boyutlu düzenli dizi tanımlama
int[,,] intUcBDizi = new int[2,3,2];
//3 boyutlu düzenli diziye değer atama
intUcBDizi[0, 0, 0] = 1;
intUcBDizi[0, 0, 1] = 34;
intUcBDizi[1, 1, 0] = 156;
//3 boyutlu düzensiz dizi tanımlama
int[][][] intUcBDuzensizDizi = new int[2][][];
//3 boyutlu düzensiz dizinin alt elemanlarını ayarlama
intUcBDuzensizDizi[0] = new int[2][];
intUcBDuzensizDizi[0][0] = new int[3];
intUcBDuzensizDizi[0][1] = new int[4];
intUcBDuzensizDizi[1] = new int[3][];
intUcBDuzensizDizi[1][0] = new int[2];
intUcBDuzensizDizi[1][1] = new int[5];
intUcBDuzensizDizi[1][2] = new int[3];
//3 boyutlu düzensiz diziye değer atama
intUcBDuzensizDizi[0][0][0] = 129;
intUcBDuzensizDizi[0][0][1] = 65;
intUcBDuzensizDizi[0][1][0] = 119;
intUcBDuzensizDizi[0][1][1] = 35;
intUcBDuzensizDizi[1][1][1] = 30;
intUcBDuzensizDizi[1][2][1] = 37;
Örneklerimizde hep integer tipinde veri tutan dizilerden bahsettik. Örneklerle string değer tutan dizilerin nasıl kullanıldığını aşağıda verilmektedir.
string[] isim = new string[4];
Dizi elemanlarının değerlerini oluşturma anında vermek
string[] isim = new string[4]{"Sabri","Seher","Ali","Metin"};
//veya
string[] isim2 = new string[] { "Sabri", "Seher", "Ali", "Metin" };
//veya
string[] isim3 = { "Sabri", "Seher", "Ali", "Metin" };
//veya tanımlama ve değer oluşturma işlemini ayrı satırlarda yapma
string[] isim4;
isim4 = new string[4] { "Sabri", "Seher", "Ali", "Metin" };
İlk oluşturma anında elemanlara değer verme işlemini 2 boyutlu dizilerde de aşağıdaki gibi yapabiliriz.
string[][] isimListesi = { new string[] { "Sabri", "Seher" }, new string[] { "Ahmet", "Mehmet", "Zuhal", } };
KOLEKSİYONLAR
Birçok uygulama için ilgili nesnelerin gruplarını oluşturmak ve yönetmek istersiniz. Nesneler iki şekilde gruplanabilir, nesne dizisi oluşturarak veya nesne koleksiyonu oluşturarak.
Diziler, türü kesin olarak belirtilmiş sabit sayıdaki nesneleri oluştururken veya bunlarla çalışırken ekseriyetle faydalıdır.
Koleksiyonlar nesne grupları ile çalışmak üzere daha esnek bir yol sağlar. Dizilerden farklı olarak çalıştığınız nesne grupları, uygulamanın ihtiyacına göre dinamik olarak büyüyebilir ve küçülebilir. Bazı koleksiyonlar için koleksiyona eklediğiniz herhangi bir nesne için bir tuşa atayabilirsiniz böylece tuşu kullanarak nesneyi kolayca çağırabilirsiniz.
Koleksiyon bir sınıftır, bu nedenle yeni bir koleksiyona öğeleri eklemeden önce bu koleksiyonun bildirmelisiniz.
Koleksiyonunuz tek bir veri türünde öğeler içeriyorsa System.Collections.Generic ad alanını içindeki sınıflardan birini kullanabilirsiniz. Genel koleksiyon tür güvenliği sağlar. Bu sayede başka bir veri türü eklenemez. Bir genel koleksiyondan öğe aldığınızda veri türünü belirlemeniz veya dönüştürmeniz gerekmez.
Koleksiyon Türleri
•
ArrayList
•
SortedList
•
HashTable
•
BitArray
•
Stack
•
Queue
Bunların System.Array altında bulunan klasik array gibidir fakat array’lerde kullanmadığımız bir çok metodu bu sınıflarda kullanabiliriz. Ayrıca array’lerde var olan oluştururken boyutunu verme zorunluğu veya boyutunu aşınca hata vermesi gibi canımızı sıkan şeyler burada yoktur. Fakat array’lar oluşturulurken boyutu verildiği için her ne kadar bellekte yer kaplıyor desekte casting işlemi yapılmadığı için yinede bir artışı vardır.
Array
Yukarıda bahsettiğimiz klasik array’dir. Oluşturulurken boyutunun verilmesi gerekmektedir. Boyutunu aşınca hata verir. Array sınıfı abstract bir sınıftır yani kullanılacağı zaman new sözcüğü ile instance’ının yaratılmasına gerek yoktur. Add,Remove,Sort,IndextOf,FindIndex gibi Collection’larda kullandığımız metolara sahip değildir.
Bu yüzden esnek bir yapıya sahip değildir.
ArrayList
Index-base bir yapıdır. Aslında array gibidir fakat klasik array’den farkı oluştururken boyutunu vermemize gerek yoktur. Add metodu ile yeni öğeler ekledikçe boyutu otomatik artar. Bu yüzden bellekte boşuna yer kaplamaz.Bu bakımdan iyidir fakat sadece object tipinde veriler sakladğı için obje dışında bir öğe eklenince boxing işlemi yani gönderilen öğenin objeye çevirilme işleminin yapılması zorunludur.
Bunu kendi içinde yapar fakar bu işlem performans kaybına neden olur.
Add,Remove,Sort,IndexOf,FİndIndex gibi metodları kullanabiliriz.
Object nesneler tuttuğu için programımızda kullandığımız bir strangle bir integer arraylist içine atabiliriz. Bu string ve integer arraylist tarafından objeye çevirip saklanır.
SortedList
Key/Value adında iki adet very barındırırlar. Verilere verdiğiniz bu ‘Key’ değeri ile ulaştıkları için unique olmalıdır. Bu yüzden ‘Key ’ NULL olamaz. Sıralamayıda bu ‘Key’ değerlerini kullanarak yaparlar. Alfabetik bir sıralama söz konusudur. IndexOfKEy,IndexOfValue,RemoveAt,GetByIndex,SetByIndex gibi metodlara sahip olduğu için esnek bir yapısı vardır.
HashTable
Yapı olarak SortedList’ e yine Key/Value yapısı vardır. Farkı sıralamayı alfabetir olarak değil, ‘Key’ üzerinde Has kodlarına gore yapmasıdır. Bu özelliği onun hız bakımından SortedList’in önüne geçirsede sıraladığı veriler karmaşık olur bu kötü bir özelliğidir. Ayrıca IndexOfKey,IndexOfValue,RemoveAt,GetByIndex,SetByIndex gibi metodlar HashTable’de mevcut değildir.
Bu yüzden SortedList HastTable’ a gore daha esnek bir yapıya sahiptir
BitArray
Değişkenlerin Bit değerleriyle işlem yapılmak isteniyorsa tercih edilmelidir. İnt,boolean ve byte tiplerine izin verir. Array’lar gibi oluşturulurken boyut vermek zorunludur.
Stack
Stack LIFO (Last In First Out) mantığıyla çalışır. Yani Stact’ a son giren ilk çıkar. Veriler üzerinde dolaşmaya imkan sağlamaz. Stack yapısını bir depoya benzetebiliriz.Bir depo düşünün bu depoya mallar en son eklenen malın arkasına gelecek şekilde eklenir ve bir mal çıkarılacaksa ilk giren mala ulaşılmaz en son konulan mal çıkarılır.
Yani son giren ilk çıkar.Sadece en sondaki veriye ulaşabilir.Boyut belirtme zorunluluğu yoktur.Veri geldikçe kendi otomatik olarak arttırır.
Queue
Queue ise FIFO (First In Fırst Out) mantığıyla çalışır. Queue’de işe ilk giren çıkar.Bunuda bir banka kuyruğuna benzetebiliriz. Bankya gittiğimizde sıraya gireriz ve ilk gelen ilk çıkar. Bunun dışında Stack yapısıyla aynı özelliklere sahiptir. Yine veriler üzerinde gezme yoktur. Boyut belirtme zorunluluğu yoktur.Veri geldikçe kendi otomatik olarak arttırır.