C# ve .NET [9]
Giriş: Veri Gruplarına Olan İhtiyaç Programlarımızda genellikle tek tek değişkenlerle çalışmak yeterli olmaz. Çoğu zaman, birbiriyle ilişkili birden fazla veriyi bir arada tutmamız gerekir: bir sınıftaki öğrencilerin listesi, bir alışveriş sepetindeki ürünler, bir yapılandırma dosyasındaki ayarlar, bir kelimenin farklı dillerdeki karşılıkları vb. Bu tür veri gruplarını yönetmek için C# bize çeşitli yapılar sunar. En temel olanı dizilerdir, ancak daha fazla esneklik ve işlevsellik için .NET Koleksiyon Kütüphanesi zengin alternatifler sağlar. Bölüm 1: C# Dizileri (Arrays) — Sabit Boyutlu Temel 1.1. Tanım ve Özellikler: Tanım: Dizi, aynı türden sabit sayıda öğeyi bellekte ardışık bir şekilde saklayan bir veri yapısıdır. Sabit Boyutlu (Fixed-Size): Bir dizi oluşturulduğunda boyutu belirlenir ve bu boyut daha sonra değiştirilemez. Yeni eleman eklemek veya çıkarmak için yeni bir dizi oluşturup eski elemanları kopyalamak gerekir. Sıfır Tabanlı İndeksleme: Elemanlara 0'dan başlayan sayısal bir indeks ile erişilir (ilk eleman dizi[0], son eleman dizi[dizi.Length — 1]). Tür Güvenliği (Type Safety): Bir dizi belirli bir tür için tanımlanır (int[], string[], Ogrenci[]) ve yalnızca o türdeki (veya o türe dönüştürülebilen) değerleri saklayabilir. Referans Tipi: C#’ta diziler referans tipleridir. Yani int[] gibi değer tiplerinden oluşan bir dizi bile aslında Heap’te saklanır ve dizi değişkeni bu Heap alanına bir referans tutar. Bu, diziler metotlara geçirildiğinde veya atandığında referanslarının kopyalandığı anlamına gelir. System.Array Sınıfı: Tüm C# dizileri örtük olarak System.Array sınıfından türemiştir. Bu sınıf, diziler için Length (boyut), Rank (boyut sayısı), Sort, Reverse, IndexOf, Clear gibi birçok kullanışlı statik ve örnek metodu sağlar. 1.2. Dizi Tanımlama ve Başlatma: // 1. Bildirme ve Boyut Belirterek Oluşturma (Elemanlar varsayılan değer alır) int[] sayilar = new int[5]; // 5 elemanlık int dizisi, tümü 0 olur. string[] isimler = new string[3]; // 3 elemanlık string dizisi, tümü null olur. bool[] durumlar = new bool[2]; // 2 elemanlık bool dizisi, tümü false olur. // 2. Bildirme, Oluşturma ve Başlatma (Dizi Literali ile - Boyut otomatik belirlenir) int[] puanlar = new int[] { 85, 92, 78, 95 }; // Boyut 4 olur. // veya daha kısa (new int[] kısmı çıkarılabilir) string[] gunler = { "Pazartesi", "Salı", "Çarşamba" }; // 3. Bildirme ve Daha Sonra Oluşturma/Atama double[] oranlar; oranlar = new double[2]; oranlar[0] = 0.18; oranlar[1] = 0.08; // Boyutu sonradan değiştirilemez! // puanlar[4] = 100; // HATA! IndexOutOfRangeException // Array.Resize(ref puanlar, 5); // Boyut değiştirmek için Array.Resize kullanılabilir ama yeni dizi oluşturur. 1.3. Dizilere Erişim ve Döngüler: Elemanlara indeksle erişilir. Döngülerle (genellikle for veya foreach) elemanlar üzerinde gezinilir. int[] notlar = { 100, 90, 80 }; // Erişim Console.WriteLine($"İlk not: {notlar[0]}"); // 100 notlar[1] = 95; // Değiştirme Console.WriteLine($"İkinci not: {notlar[1]}"); // 95 // for döngüsü ile gezinme (indeks lazımsa) Console.WriteLine("\nNotlar (for):"); for (int i = 0; i < notlar.Length; i++) { Console.WriteLine($"İndeks {i}: {notlar[i]}"); } // foreach döngüsü ile gezinme (daha basit ve okunabilir) Console.WriteLine("\nNotlar (foreach):"); foreach (int not in notlar) // Koleksiyondaki her 'not' için { Console.WriteLine(not); } 1.4. Çok Boyutlu Diziler (Multidimensional Arrays): Tablolar veya matrisler gibi yapıları temsil etmek için kullanılırlar. Dikdörtgen Diziler (Rectangular Arrays): Tüm satırların aynı sayıda sütuna sahip olduğu dizilerdir. // 2 satır, 3 sütunluk int matrisi int[,] matris = new int[2, 3]; matris[0, 0] = 1; matris[0, 1] = 2; matris[0, 2] = 3; matris[1, 0] = 4; matris[1, 1] = 5; matris[1, 2] = 6; // Literal ile başlatma int[,] matris2 = { { 1, 2, 3 }, { 4, 5, 6 } }; Console.WriteLine(matris2[1, 1]); // 5 Console.WriteLine($"Satır sayısı: {matris2.GetLength(0)}"); // 2 Console.WriteLine($"Sütun sayısı: {matris2.GetLength(1)}"); // 3 // İç içe for ile gezinme for (int satir = 0; satir < matris2.GetLength(0); satir++) { for (int sutun = 0; sutun < matris2.GetLength(1); sutun++) { Console.Write(matris2[satir, sutun] + " "); } Console.WriteLine(); } Düzensiz Diziler (Jagged Arrays): Dizi içinde dizi barındıran yapılardır. İçteki dizilerin boyutları farklı olabilir. int[][] jaggedArray = new int[3][]; // 3 tane int dizisi tutabilen bir dizi jaggedArray[0] = new int[] { 1, 2 }; // İlk satır 2 elemanlı jaggedArray[1] = new int[] { 3, 4, 5, 6 }; // İkinci satır 4 elemanlı jaggedArray[2] = new int[] { 7 }; // Üçüncü satır 1 elemanlı Console.WriteLine(jaggedArray[1][2]); // 5 // İç içe for/foreach ile gezinme foreach (int[] satir in jaggedArray) { foreach (int eleman in satir) { Console.Write(eleman + " "); } Console.WriteLine(); } 1.5. Dizilerin Dezavantajları: Sabit Boyut: En büyük kısıtlamasıdır. Çalışma zamanında boyutunu değiştirmek verimsizdir (yeni dizi oluşturup kopyalama gerekir). Ekleme/Silme Zorluğu:
![C# ve .NET [9]](https://media2.dev.to/dynamic/image/width%3D1000,height%3D500,fit%3Dcover,gravity%3Dauto,format%3Dauto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0yuyr4860jpx2hqlowuz.png)
Giriş: Veri Gruplarına Olan İhtiyaç
Programlarımızda genellikle tek tek değişkenlerle çalışmak yeterli olmaz. Çoğu zaman, birbiriyle ilişkili birden fazla veriyi bir arada tutmamız gerekir: bir sınıftaki öğrencilerin listesi, bir alışveriş sepetindeki ürünler, bir yapılandırma dosyasındaki ayarlar, bir kelimenin farklı dillerdeki karşılıkları vb. Bu tür veri gruplarını yönetmek için C# bize çeşitli yapılar sunar. En temel olanı dizilerdir, ancak daha fazla esneklik ve işlevsellik için .NET Koleksiyon Kütüphanesi zengin alternatifler sağlar.
Bölüm 1: C# Dizileri (Arrays) — Sabit Boyutlu Temel
1.1. Tanım ve Özellikler:
Tanım: Dizi, aynı türden sabit sayıda öğeyi bellekte ardışık bir şekilde saklayan bir veri yapısıdır.
Sabit Boyutlu (Fixed-Size): Bir dizi oluşturulduğunda boyutu belirlenir ve bu boyut daha sonra değiştirilemez. Yeni eleman eklemek veya çıkarmak için yeni bir dizi oluşturup eski elemanları kopyalamak gerekir.
Sıfır Tabanlı İndeksleme: Elemanlara 0'dan başlayan sayısal bir indeks ile erişilir (ilk eleman dizi[0], son eleman dizi[dizi.Length — 1]).
Tür Güvenliği (Type Safety): Bir dizi belirli bir tür için tanımlanır (int[], string[], Ogrenci[]) ve yalnızca o türdeki (veya o türe dönüştürülebilen) değerleri saklayabilir.
Referans Tipi: C#’ta diziler referans tipleridir. Yani int[] gibi değer tiplerinden oluşan bir dizi bile aslında Heap’te saklanır ve dizi değişkeni bu Heap alanına bir referans tutar. Bu, diziler metotlara geçirildiğinde veya atandığında referanslarının kopyalandığı anlamına gelir.
System.Array Sınıfı: Tüm C# dizileri örtük olarak System.Array sınıfından türemiştir. Bu sınıf, diziler için Length (boyut), Rank (boyut sayısı), Sort, Reverse, IndexOf, Clear gibi birçok kullanışlı statik ve örnek metodu sağlar.
1.2. Dizi Tanımlama ve Başlatma:
// 1. Bildirme ve Boyut Belirterek Oluşturma (Elemanlar varsayılan değer alır)
int[] sayilar = new int[5]; // 5 elemanlık int dizisi, tümü 0 olur.
string[] isimler = new string[3]; // 3 elemanlık string dizisi, tümü null olur.
bool[] durumlar = new bool[2]; // 2 elemanlık bool dizisi, tümü false olur.
// 2. Bildirme, Oluşturma ve Başlatma (Dizi Literali ile - Boyut otomatik belirlenir)
int[] puanlar = new int[] { 85, 92, 78, 95 }; // Boyut 4 olur.
// veya daha kısa (new int[] kısmı çıkarılabilir)
string[] gunler = { "Pazartesi", "Salı", "Çarşamba" };
// 3. Bildirme ve Daha Sonra Oluşturma/Atama
double[] oranlar;
oranlar = new double[2];
oranlar[0] = 0.18;
oranlar[1] = 0.08;
// Boyutu sonradan değiştirilemez!
// puanlar[4] = 100; // HATA! IndexOutOfRangeException
// Array.Resize(ref puanlar, 5); // Boyut değiştirmek için Array.Resize kullanılabilir ama yeni dizi oluşturur.
1.3. Dizilere Erişim ve Döngüler:
Elemanlara indeksle erişilir. Döngülerle (genellikle for veya foreach) elemanlar üzerinde gezinilir.
int[] notlar = { 100, 90, 80 };
// Erişim
Console.WriteLine($"İlk not: {notlar[0]}"); // 100
notlar[1] = 95; // Değiştirme
Console.WriteLine($"İkinci not: {notlar[1]}"); // 95
// for döngüsü ile gezinme (indeks lazımsa)
Console.WriteLine("\nNotlar (for):");
for (int i = 0; i < notlar.Length; i++)
{
Console.WriteLine($"İndeks {i}: {notlar[i]}");
}
// foreach döngüsü ile gezinme (daha basit ve okunabilir)
Console.WriteLine("\nNotlar (foreach):");
foreach (int not in notlar) // Koleksiyondaki her 'not' için
{
Console.WriteLine(not);
}
1.4. Çok Boyutlu Diziler (Multidimensional Arrays):
Tablolar veya matrisler gibi yapıları temsil etmek için kullanılırlar.
Dikdörtgen Diziler (Rectangular Arrays): Tüm satırların aynı sayıda sütuna sahip olduğu dizilerdir.
// 2 satır, 3 sütunluk int matrisi int[,] matris = new int[2, 3]; matris[0, 0] = 1; matris[0, 1] = 2; matris[0, 2] = 3; matris[1, 0] = 4; matris[1, 1] = 5; matris[1, 2] = 6; // Literal ile başlatma int[,] matris2 = { { 1, 2, 3 }, { 4, 5, 6 } }; Console.WriteLine(matris2[1, 1]); // 5 Console.WriteLine($"Satır sayısı: {matris2.GetLength(0)}"); // 2 Console.WriteLine($"Sütun sayısı: {matris2.GetLength(1)}"); // 3 // İç içe for ile gezinme for (int satir = 0; satir < matris2.GetLength(0); satir++) { for (int sutun = 0; sutun < matris2.GetLength(1); sutun++) { Console.Write(matris2[satir, sutun] + " "); } Console.WriteLine(); }
Düzensiz Diziler (Jagged Arrays): Dizi içinde dizi barındıran yapılardır. İçteki dizilerin boyutları farklı olabilir.
int[][] jaggedArray = new int[3][]; // 3 tane int dizisi tutabilen bir dizi jaggedArray[0] = new int[] { 1, 2 }; // İlk satır 2 elemanlı jaggedArray[1] = new int[] { 3, 4, 5, 6 }; // İkinci satır 4 elemanlı jaggedArray[2] = new int[] { 7 }; // Üçüncü satır 1 elemanlı Console.WriteLine(jaggedArray[1][2]); // 5 // İç içe for/foreach ile gezinme foreach (int[] satir in jaggedArray) { foreach (int eleman in satir) { Console.Write(eleman + " "); } Console.WriteLine(); }
1.5. Dizilerin Dezavantajları:
Sabit Boyut: En büyük kısıtlamasıdır. Çalışma zamanında boyutunu değiştirmek verimsizdir (yeni dizi oluşturup kopyalama gerekir).
Ekleme/Silme Zorluğu: Ortadan eleman eklemek veya silmek, sonraki elemanları kaydırmayı gerektirir ve verimsizdir.
Bu dezavantajlar nedeniyle, boyutu çalışma zamanında değişebilen veya sık sık eleman eklenip çıkarılması gereken durumlar için Koleksiyonlar çok daha uygun bir alternatiftir.
Bölüm 2: Generic Koleksiyonlara Giriş ve List
.NET Framework (ve sonraki .NET sürümleri), System.Collections ve özellikle System.Collections.Generic isim alanları altında zengin bir koleksiyon sınıfları seti sunar. Generic (Tür Bağımsız) Koleksiyonlar (System.Collections.Generic), belirli bir veri türüyle (T ile temsil edilir) çalışacak şekilde tasarlanmıştır ve şu avantajları sunar:
Tür Güvenliği: Koleksiyona yalnızca belirtilen türdeki (T) öğeler eklenebilir. Bu, derleme zamanında tür hatalarını yakalamayı sağlar ve çalışma zamanı InvalidCastException riskini azaltır.
Performans: Değer tipleriyle çalışırken gereksiz boxing/unboxing işlemlerini ortadan kaldırır.
Okunabilirlik: Kodun hangi tür veriyi sakladığı daha nettir.
Eski, generic olmayan koleksiyonlar (ArrayList, Hashtable vb. System.Collections altında) hala mevcut olsa da, yeni kodlarda kesinlikle generic koleksiyonların kullanılması önerilir.
2.1. List — Dinamik Boyutlu Dizi
Tanım: System.Collections.Generic isim alanında bulunan, belirli bir T türündeki öğeleri saklayan, dinamik boyutlu, sıralı bir listedir. Arka planda bir dizi kullanır, ancak gerektiğinde bu dizinin boyutunu otomatik olarak yönetir.
Temel Özellikler:
Dinamik Boyut: Öğeler eklendikçe veya çıkarıldıkça boyutu otomatik olarak ayarlanır.
Tür Güvenliği: Sadece T türündeki öğeleri kabul eder.
Sıralı Erişim: Öğelere sıfır tabanlı indeks ile erişilir (liste[index]).
Kolay Ekleme/Silme: Başa, sona veya araya kolayca eleman ekleme ve çıkarma metotları sunar.
Zengin Metot Seti: Ekleme, silme, arama, sıralama, dönüştürme gibi birçok kullanışlı metoda sahiptir.
Referans Tipi: List sınıfının kendisi bir referans tipidir.
2.2. List Oluşturma ve Başlatma:
using System.Collections.Generic;
// Boş bir string listesi oluşturma
List isimlerListesi = new List();
// Başlangıç kapasitesi belirterek oluşturma (performans ipucu)
List sayilarListesi = new List(10); // Başlangıçta 10 elemanlık yer ayırır
// Başlangıç değerleriyle oluşturma (Koleksiyon Başlatıcı - Collection Initializer)
List fiyatlar = new List { 19.99, 10.50, 125.0 };
// Mevcut bir diziden veya başka bir koleksiyondan oluşturma
string[] mevcutIsimler = { "Zeynep", "Osman" };
List yeniIsimListesi = new List(mevcutIsimler);
2.3. Temel List İşlemleri ve Metotları:
List sehirler = new List { "İstanbul", "Ankara" };
// Eleman Ekleme
sehirler.Add("İzmir"); // Sona ekler -> ["İstanbul", "Ankara", "İzmir"]
sehirler.Insert(1, "Bursa"); // 1. indekse ekler -> ["İstanbul", "Bursa", "Ankara", "İzmir"]
List eklenecekler = new List { "Antalya", "Adana" };
sehirler.AddRange(eklenecekler); // Başka bir koleksiyonu sona ekler
// Elemana Erişim
Console.WriteLine($"İlk şehir: {sehirler[0]}"); // İstanbul
sehirler[2] = "ANKARA"; // Değeri değiştirme
// Eleman Sayısı (Count özelliği, Length değil!)
Console.WriteLine($"Şehir sayısı: {sehirler.Count}"); // 6
// Eleman Arama
bool izmirVarMi = sehirler.Contains("İzmir"); // true
int bursaIndex = sehirler.IndexOf("Bursa"); // 1
int adanaIndex = sehirler.LastIndexOf("Adana"); // 5 (varsa son indeksi)
int trabzonIndex = sehirler.IndexOf("Trabzon"); // -1 (bulunamazsa)
// Koşula Göre Arama (LINQ veya Predicate kullanır)
string? buyukAİleBaslayan = sehirler.Find(s => s.StartsWith("A")); // "Ankara" (ilk eşleşen)
List aIleBaslayanlar = sehirler.FindAll(s => s.StartsWith("A")); // ["ANKARA", "Antalya", "Adana"]
int ilkBesHarfliIndex = sehirler.FindIndex(s => s.Length == 5); // Bursa'nın indeksi: 1
// Eleman Silme
bool bursaSilindiMi = sehirler.Remove("Bursa"); // true (ilk bulduğunu siler)
sehirler.RemoveAt(0); // 0. indekstekini siler ("İstanbul")
int silinenSayi = sehirler.RemoveAll(s => s.Length > 6); // 6 harften uzun olanları siler (Antalya) -> silinenSayi=1
// sehirler.Clear(); // Tüm listeyi temizler
// Listede Gezinme (foreach önerilir)
Console.WriteLine("\nŞehirler:");
foreach (string sehir in sehirler)
{
Console.WriteLine($"- {sehir}");
}
// Diğer Kullanışlı Metotlar
// sehirler.Sort(); // Yerinde sıralama (varsayılan string sıralaması)
// sehirler.Reverse(); // Yerinde ters çevirme
bool hepsiUzunMu = sehirler.TrueForAll(s => s.Length > 3); // Hepsi 3 harften uzun mu?
List sehirUzunluklari = sehirler.ConvertAll(s => s.Length); // Yeni bir uzunluk listesi oluşturur
1.5. Diziler vs. List:
Boyut: Diziler sabit boyutlu, List dinamik boyutlu.
Performans: Sabit boyutlu erişim için diziler genellikle biraz daha hızlıdır (indeksle doğrudan erişim). Ancak List’nin dinamik boyut yönetimi de oldukça optimize edilmiştir. Sona eleman ekleme (Add) genellikle hızlıdır (kapasite aşılmadıkça). Ortaya ekleme/çıkarma (Insert, RemoveAt) listede kaydırma gerektirdiği için daha yavaş olabilir.
Esneklik: List, eleman ekleme, çıkarma ve diğer işlemler için çok daha fazla yerleşik metot ve esneklik sunar.
Kural: Boyutun sabit olduğu ve değişmeyeceği biliniyorsa veya maksimum performans kritikse dizi kullanılabilir. Diğer çoğu durumda, özellikle eleman sayısının değişebileceği veya sık sık ekleme/çıkarma yapılacağı senaryolarda List genellikle daha iyi ve daha pratik bir seçimdir.
Bölüm 3: Dictionary — Anahtar-Değer Koleksiyonu
3.1. Tanım ve Özellikler:
Tanım: System.Collections.Generic isim alanında bulunan, benzersiz anahtarlara (keys) karşılık gelen değerleri (values) saklayan bir koleksiyondur. Sözlük, harita (map) veya ilişkisel dizi (associative array) olarak da bilinir.
Anahtar-Değer Çiftleri: Her öğe bir anahtar ve bir değerden oluşur.
Benzersiz Anahtarlar: Bir Dictionary içinde her anahtar benzersiz olmalıdır. Aynı anahtarla ikinci bir değer eklenmeye çalışılırsa hata verir veya [] indeksiyle yapılırsa mevcut değerin üzerine yazar.
Hızlı Erişim: Anahtarları kullanarak değerlere çok hızlı bir şekilde erişim sağlar. Arka planda genellikle bir hash tablosu (hash table) veri yapısı kullanır, bu da ortalama olarak O(1) (sabit zamanlı) erişim, ekleme ve silme performansı sunar (hash çakışmaları olmadığında).
Tür Güvenliği: Hem anahtar (TKey) hem de değer (TValue) için belirli türler tanımlanır.
Sırasız (Genellikle): .NET’in eski sürümlerinde ve genel uygulamada, Dictionary’deki öğelerin belirli bir sırada tutulacağı garanti edilmez. Üzerinde gezinirken öğelerin eklenme sırasıyla gelmeyebilir. (.NET Core 3.0 ve sonrasında eklenme sırasını koruma eğilimi vardır ancak buna güvenmek yerine sıraya ihtiyaç varsa SortedDictionary veya List gibi yapılar düşünülmelidir.)
Referans Tipi: Dictionary sınıfı bir referans tipidir.
3.2. Dictionary Oluşturma ve Başlatma:
using System.Collections.Generic;
// String anahtar, int değer tutan boş bir sözlük
Dictionary yaslarSozluk = new Dictionary();
// Başlangıç kapasitesi belirterek
Dictionary urunAdlari = new Dictionary(50);
// Başlangıç değerleriyle oluşturma (Koleksiyon Başlatıcı)
Dictionary baskentler = new Dictionary
{
{ "Türkiye", "Ankara" }, // { anahtar, değer }
{ "Almanya", "Berlin" },
{ "Fransa", "Paris" }
// ["İtalya"] = "Roma" // C# 6+ İndeks başlatıcı sözdizimi
};
// C# 6+ İndeks Başlatıcı Sözdizimi
Dictionary renkKodlari = new Dictionary
{
["Kırmızı"] = "#FF0000",
["Yeşil"] = "#00FF00",
["Mavi"] = "#0000FF"
};
3.3. Temel Dictionary İşlemleri ve Metotları:
Dictionary urunFiyatlari = new Dictionary();
// Eleman Ekleme
urunFiyatlari.Add("Elma", 3.5);
urunFiyatlari.Add("Muz", 7.0);
urunFiyatlari.Add("Portakal", 4.25);
// urunFiyatlari.Add("Elma", 4.0); // Hata! ArgumentException: Aynı anahtar zaten var.
// Değere Erişim ve Değiştirme (İndeksleyici [])
// Anahtar varsa değeri döndürür, yoksa KeyNotFoundException fırlatır!
Console.WriteLine($"Elma Fiyatı: {urunFiyatlari["Elma"]}"); // 3.5
// Değer değiştirme veya yeni ekleme (eğer anahtar yoksa ekler)
urunFiyatlari["Muz"] = 7.5; // Mevcut değeri günceller
urunFiyatlari["Kivi"] = 9.0; // Yeni anahtar-değer çifti ekler
Console.WriteLine($"Muz Fiyatı: {urunFiyatlari["Muz"]}"); // 7.5
Console.WriteLine($"Kivi Fiyatı: {urunFiyatlari["Kivi"]}"); // 9.0
// Eleman Sayısı
Console.WriteLine($"Ürün Sayısı: {urunFiyatlari.Count}"); // 4
// Anahtar Kontrolü (Exception almamak için önemlidir)
if (urunFiyatlari.ContainsKey("Portakal"))
{
Console.WriteLine($"Portakal fiyatı mevcut: {urunFiyatlari["Portakal"]}");
} else {
Console.WriteLine("Portakal bulunamadı.");
}
// Değer Kontrolü
bool yediBuçukVarMi = urunFiyatlari.ContainsValue(7.5); // true
// Güvenli Değer Alma (TryGetValue) - En İyi Yöntem
double kiviFiyati;
if (urunFiyatlari.TryGetValue("Kivi", out kiviFiyati)) // Anahtar varsa true döner, değeri out parametresine atar
{
Console.WriteLine($"Kivi Fiyatı (TryGetValue): {kiviFiyati}"); // 9.0
}
else
{
Console.WriteLine("Kivi bulunamadı (TryGetValue).");
}
double armutFiyati;
if (urunFiyatlari.TryGetValue("Armut", out armutFiyati))
{
Console.WriteLine($"Armut Fiyatı (TryGetValue): {armutFiyati}");
}
else
{
Console.WriteLine("Armut bulunamadı (TryGetValue)."); // Bu çalışır
}
// Eleman Silme
bool portakalSilindiMi = urunFiyatlari.Remove("Portakal"); // true (silinirse)
// urunFiyatlari.Clear(); // Tüm sözlüğü temizler
// Sözlükte Gezinme (foreach ile KeyValuePair)
Console.WriteLine("\nÜrünler ve Fiyatları:");
foreach (KeyValuePair kvp in urunFiyatlari)
{
Console.WriteLine($"- {kvp.Key}: {kvp.Value:C}"); // :C para birimi formatı
}
// veya var ile
// foreach (var kvp in urunFiyatlari) { ... }
// Sadece Anahtarlar Üzerinde Gezinme
Console.WriteLine("\nSadece Ürün Adları:");
foreach (string urunAdi in urunFiyatlari.Keys) // Keys özelliği ICollection döndürür
{
Console.WriteLine($"- {urunAdi}");
}
// Sadece Değerler Üzerinde Gezinme
Console.WriteLine("\nSadece Fiyatlar:");
foreach (double fiyat in urunFiyatlari.Values) // Values özelliği ICollection döndürür
{
Console.WriteLine($"- {fiyat:F2}"); // F2: 2 ondalık hane
}
3.4. Dictionary vs. List:
Erişim: Dictionary anahtarla çok hızlı (O(1)) erişim sağlar. List’de belirli bir öğeyi bulmak için (eğer indeksini bilmiyorsak) tüm listeyi veya bir kısmını aramak gerekebilir (O(n) veya Contains gibi optimize edilmiş metotlarla daha hızlı olabilir ama yine de anahtar kadar hızlı değildir). Doğru koleksiyon türünü seçmek önemlidir:
Sabit boyutlu, aynı türden öğeler: Array ( Tip[] ) Bölüm 5: Performans Konuları
List Kapasitesi: List, eleman eklendikçe arka plandaki dizinin kapasitesini otomatik olarak artırır. Kapasite aşıldığında, genellikle mevcut kapasiteyi ikiye katlayarak yeni, daha büyük bir dizi oluşturur ve eski elemanları kopyalar. Bu, sık sık küçük eklemeler yapıldığında maliyetli olabilir. Eğer eklenecek eleman sayısı önceden kabaca biliniyorsa, List’yi başlangıç kapasitesiyle oluşturmak (new List(tahminiBoyut)) bu yeniden boyutlandırma işlemlerini azaltabilir. C#’taki diziler ve özellikle generic koleksiyonlar olan List ve Dictionary, verileri etkili bir şekilde gruplamak, saklamak ve yönetmek için vazgeçilmez araçlardır.
Diziler, sabit boyutlu, aynı türden öğeler için temel ve performanslı bir yapı sunar. Abdulkadir Güngör - Kişisel WebSite
Sıralama: List sıralıdır, elemanlar eklendiği sırada veya sıralandıktan sonraki sırada kalır. Dictionary genellikle sırasızdır.
Kullanım Alanı: Değerlere benzersiz bir anahtarla hızlıca erişmek gerekiyorsa (Dictionary). Öğelerin belirli bir sırada olması veya sıklıkla indeksle erişilmesi gerekiyorsa (List
Dinamik boyutlu, sıralı, indeksle erişilen öğeler: List (En yaygın)
Benzersiz anahtarla hızlı değer erişimi: Dictionary
Sıralı anahtar-değer çiftleri: SortedList (Anahtara göre sıralı tutar, erişim biraz daha yavaş olabilir) veya SortedDictionary (Daha hızlı ekleme/çıkarma, ağaç yapısı kullanır).
Benzersiz öğelerden oluşan sırasız koleksiyon: HashSet (Bir öğenin koleksiyonda olup olmadığını çok hızlı kontrol etmek için ideal).
Benzersiz öğelerden oluşan sıralı koleksiyon: SortedSet
LIFO (Son Giren İlk Çıkar) davranışı: Stack (Push, Pop)
FIFO (İlk Giren İlk Çıkar) davranışı: Queue (Enqueue, Dequeue)
Bunların dışında LinkedList, ObservableCollection (UI bağlama için) gibi daha özel koleksiyonlar da mevcuttur.
Dictionary Hash Çakışmaları: Dictionary’nin performansı büyük ölçüde hash fonksiyonunun kalitesine ve anahtarların dağılımına bağlıdır. Kötü bir hash fonksiyonu veya çok sayıda hash çakışması, performansı O(1)’den O(n)’ye düşürebilir. Ancak .NET’in yerleşik hash mekanizmaları genellikle oldukça iyidir. Anahtar olarak kullanılan türlerin GetHashCode() ve Equals() metotlarını doğru bir şekilde uygulaması önemlidir (özel sınıflar için).
Iterasyon: foreach genellikle koleksiyonlar üzerinde gezinmenin en okunabilir ve genellikle yeterince performanslı yoludur. Çok büyük koleksiyonlarda performans kritikse, for döngüsü ile indeks üzerinden erişim (List için) bazen biraz daha hızlı olabilir.
Bölüm 6: Sonuç — Veri Yönetiminin Temel Araçları
List, dizilerin sabit boyut kısıtlamasını ortadan kaldırarak dinamik olarak büyüyüp küçülebilen, sıralı, tür güvenli ve zengin metotlara sahip esnek bir liste yapısı sağlar. Çoğu genel amaçlı koleksiyon ihtiyacı için idealdir.
Dictionary, benzersiz anahtarlar aracılığıyla değerlere çok hızlı erişim sağlayarak veri arama ve ilişkilendirme işlemlerini optimize eder. Yapılandırma verileri, önbellekler veya öğeleri ID’lerine göre saklamak gibi senaryolar için mükemmeldir.
Doğru veri yapısını seçmek, uygulamanızın performansını, okunabilirliğini ve bakım kolaylığını doğrudan etkiler. Bu temel koleksiyonların ne zaman ve nasıl kullanılacağını anlamak, her C# geliştiricisinin sahip olması gereken temel bir beceridir. Generic koleksiyonların sunduğu tür güvenliği ve performans avantajları, onları modern C# geliştirmede standart tercih haline getirmiştir.
Abdulkadir Güngör - Kişisel WebSite
Abdulkadir Güngör - Özgeçmiş
Github
Github
Linkedin