C# 15'in geri kalanı: bilinmeye değer küçük özellikler
C# 15, Kasım'da .NET 11 ile yayınlanacak ve union types dışında günlük koddaki sürtünmeyi azaltan küçük değişiklikler de getiriyor. Yazı; with(...) collection expression argümanlarını, extension indexer'ları, labeled break/continue'yu ve preview aşamasındaki yeni unsafe modelini kuralları ve tuzaklarıyla anlatıyor.
Kilit noktalar
- with(...) collection expression'ın ilk ve tek elemanı olmak zorunda; array, span tipleri ve dynamic argümanlarla çalışmıyor.
- Capacity yalnızca oluşturmadan sonra ekleme yapacaksanız işe yarıyor; spread kaynağının sayısı biliniyorsa compiler sonucu zaten önceden boyutluyor.
- Extension indexer'lar gerçek instance indexer'a ve compiler'ın otomatik Index/Range indexer'larına yeniliyor; array ve string üzerinde hiç kullanılmıyor.
- IEnumerable<T> üzerinde ElementAt ile yazılan bir indexer, döngüyü O(n²) hale getirebilir ya da her erişimde deferred EF Core sorgusunu yeniden çalıştırabilir.
- Labeled break döngüleri ve switch'leri hedefleyebiliyor, labeled continue yalnızca döngüleri; label doğrudan o ifadenin üstünde olmalı.
- Yeni memory safety kuralları LangVersion preview ve updated-memory-safety-rules switch'ini gerektiriyor; unsafe üyeler artık çağıranlara yayılıyor.
C# 15, Kasım'da .NET 11 ile birlikte geliyor ve union types ile closed hierarchies dışında günlük kodu kısaltan küçük özellikler de getiriyor. En pratik olanı collection expression içinde ilk eleman olarak yazılan with(...): argümanlar, named argument'lar dahil, koleksiyonun constructor'ına gidiyor; böylece [with(StringComparer.OrdinalIgnoreCase)] büyük-küçük harf duyarsız bir HashSet<T> veriyor. Capacity, List<T> ile IList<T>/ICollection<T> hedeflerinde kabul ediliyor; read-only arayüzlerde yalnızca boş with() çalışıyor, array ve span tipleri desteklenmiyor.
Extension indexer'lar C# 14'teki extension member'ları tamamlıyor: extension bloğu içinde tanımlanan indexer, sahibi olmadığınız tiplere köşeli parantez kazandırıyor; User.FindFirst(ClaimTypes.Email)?.Value yerine User[ClaimTypes.Email] yazılabiliyor. Fakat bu bir fallback: gerçek instance indexer ve compiler'ın Index/Range indexer'ları önce geliyor, array ve string üzerindekiler hiç kullanılmıyor. Labeled break/continue iç içe döngüleri ve switch'leri adla terk etmeyi sağlıyor; yeniden tasarlanan unsafe model ise feature switch arkasında, yalnızca preview.
Gerçek dünyada kullanımı
- Kayıt e-postalarını StringComparer.OrdinalIgnoreCase ile kurulmuş bir HashSet<string> içinde tutan ve büyük-küçük harf yüzünden login hatası vermeyen bir servis.
- Claim değerlerini her yerde FindFirst()?.Value zincirlemek yerine User[ClaimTypes.Email] ile okuyan bir ASP.NET Core endpoint'i.
- İç içe warehouse ve bin koleksiyonlarını tarayıp ilk eşleşen SKU'da durması gereken bir depo rezervasyon rutini.
- Oluşturulurken comparer verilmesi gereken TagSet gibi [CollectionBuilder] ile yazılmış özel bir koleksiyon tipi.
Neden önemli
Bu özellikler koleksiyon oluşturmadaki iki ayrı stili ortadan kaldırıp iç içe döngülerdeki flag değişkenlerinin yerine okunabilir label'lar koyuyor; interop yapan kütüphane yazarları da yeni pointer güvenliği kurallarını erken deneyebiliyor.