C# orta seviye 3. gün: generics, koleksiyonlar, delegate'ler ve LINQ
Bu yazı, C# öğrenme serisinin üçüncü gününde generics, koleksiyon türleri, delegate/lambda ve closure'lar, event'ler, LINQ ve iterator'ları tek tek ele alıyor. Her konu kısa bir tanım, benzetme ve örnekle anlatılıyor; ardından altı alıştırma projesinin çözümü ve o çözümün neden o şekilde yazıldığı açıklanıyor. Kodlar .NET 8 ve üzeri için top-level statements ile hazırlanmış, yani doğrudan bir console projesine yapıştırılıp çalıştırılabilir.
Kilit noktalar
- Generics'te constraint (where T : class, IEntity) yazmadan generic gövdede tip üyelerine erişilemiyor; makale bunu repository örneğiyle gösteriyor
- Generic repository'de Dictionary + TryAdd, Get/Remove için sabit zamanlı erişim ve tek adımda tekrar kontrolü sağlıyor
- Koleksiyon seçimi spesifikasyonun kendisi: yazdırma kuyruğu için Queue, undo/redo için iki Stack yeterli
- Boş kuyruk/yığın normal bir durum olduğundan Dequeue/Pop yerine TryDequeue/TryPop tercih edilmeli
- Undo/redo uygulamasında yeni bir düzenleme redo yığınını temizlemeli, aksi halde tutarsız geçmiş oluşuyor
- Tüm çözümler .NET 8+ top-level statements ile yazılmış; dotnet new console projesine kopyalanıp çalıştırılabilir
Seri, dilin temellerini ve nesne modelini geçen bir geliştiriciyi C# dilinin ifade gücüne taşımayı hedefliyor. Generics bölümünde tip parametresi ve `where T : IComparable<T>` gibi constraint'lerin derleyici tarafından nasıl denetlendiği gösteriliyor; ardından `IRepository<T>` üzerinden `class, IEntity` kısıtıyla generic bir in-memory repository yazılıyor ve `Dictionary` anahtarlaması ile `TryAdd` sayesinde tekrar eden kayıtların nasıl reddedildiği anlatılıyor.
Koleksiyonlar bölümü `HashSet<T>`, `Queue<T>`, `Stack<T>` ve `SortedDictionary` arasındaki seçimin doğrudan bir tasarım kararı olduğunu vurguluyor: yazdırma kuyruğu FIFO, undo/redo ise LIFO olduğu için kod sıralama veya index hilesi yapmıyor. Yazı, `TryDequeue`/`TryPop` kullanımını ve yeni bir düzenlemenin redo geçmişini temizlemesi gerektiğini de hatırlatıyor. Sonraki bölümler delegate, `Func`/`Action`/`Predicate`, lambda ve closure'lara, event'lere, LINQ'ya ve `yield` ile iterator'lara ayrılmış durumda.
Gerçek dünyada kullanımı
- Birden fazla entity için aynı CRUD iskeletini paylaşan küçük bir in-memory veri katmanı veya test fake'i yazmak
- Arka planda iş kuyruğu işleyen bir worker servisinde FIFO davranışını Queue ile modellemek
- Metin veya form düzenleyicilerde geri al/yinele geçmişini iki Stack ile kurmak
- Koleksiyon döndüren API'lerde çağırana en dar arabirimi (IEnumerable<T>, IReadOnlyList<T>) verme alışkanlığı kazanmak
Neden önemli
Generics, koleksiyon seçimi ve delegate/LINQ bilgisi, günlük ASP.NET Core ve EF Core kodunda doğrudan karşılığı olan konular; buradaki alıştırmalar özellikle compile-time tip güvenliği ve doğru veri yapısı seçme refleksini kazandırıyor.