C# 12 ve .NET 8: Orta Seviye Geliştiriciler İçin Uygulamalı Rehber
Bu rehber, C# 12 dil sürümü ve .NET 8 çalışma zamanı ile birlikte gelen başlıca yenilikleri, günlük kod yazımına nasıl yansıdıkları üzerinden ele alır. Hedef kitle, temel C# söz dizimine ve .NET proje yapısına aşina orta seviye geliştiricilerdir.
Önkoşullar ve kapsam
- .NET 8 SDK kurulu bir geliştirme ortamı.
- C# 12 özellikleri,
LangVersionayarına bağlı olarak derleyici tarafından etkinleştirilir. .NET 8 projelerinde varsayılan olarak C# 12 kullanılır; hedef çerçeve farklıysa dil sürümünü proje dosyasında ayrıca belirtmeniz gerekebilir. - Bu yazıdaki örnekler, davranışı gözlemlenebilir tutmak için küçük tutulmuştur. Derleyici sürümüne veya SDK yapılandırmasına bağlı ayrıntılar için resmi belgeleri esas alın.
Birincil Oluşturucular (Primary Constructors)
C# 12 ile sınıf ve struct'lar birincil oluşturucu parametreleri alabilir. Amaç, alan tanımlama ve atama tekrarını azaltmaktır.
public class SiparisIsleyici(string musteriAdi, int adet)
{
public string Ozet() => $"{musteriAdi}: {adet} adet";
}
Buradaki musteriAdi ve adet, sınıf gövdesinde kullanılabilen parametrelerdir. Dikkat edilmesi gereken nokta şudur: birincil oluşturucu parametreleri otomatik olarak public özelliklere dönüşmez. Yalnızca gövde içinde erişilebilirler; dışarıya açmak istiyorsanız özellik tanımlamanız gerekir.
Yaygın hata: Birincil oluşturucu parametresini bir metot içinde yakalayıp sonradan kullanmaya çalışmak, beklenmedik yaşam süresi davranışlarına yol açabilir. Parametrenin sınıf ömrü boyunca saklanması gerekiyorsa açık bir alan veya özellik tanımlamak daha öngörülebilirdir.
Koleksiyon İfadeleri (Collection Expressions)
Koleksiyon ifadeleri, dizi ve liste oluşturmayı sadeleştirir:
int[] sayilar = [1, 2, 3];
List<string> isimler = ["Ali", "Ayşe"];
Köşeli parantez söz dizimi, hedef türe göre uygun koleksiyon türüne dönüştürülür. Yayılma (spread) operatörü .. ile mevcut koleksiyonlar birleştirilebilir:
int[] a = [1, 2];
int[] b = [3, 4];
int[] birlesik = [.. a, .. b];
Beklenen davranış: birlesik dizisi dört eleman içerir. Bu söz dizimi, hedef tür belirli olduğunda derleyici tarafından uygun oluşturma koduna çevrilir; hedef tür belirsizse derleme hatası alırsınız.
Birincil Oluşturucularla Kayıtlar ve with İfadesi
Kayıtlar (record) zaten birincil oluşturucu söz dizimini kullanıyordu; C# 12 bunu sınıf ve struct'lara genişletti. Kayıtların with ifadesiyle kopyalama davranışı değişmedi:
public record Nokta(int X, int Y);
var p1 = new Nokta(1, 2);
var p2 = p1 with { Y = 5 };
p2, X = 1 ve Y = 5 değerlerine sahiptir; p1 değişmez.
using Diğer Adları (Alias Any Type)
C# 12, using yönergesiyle herhangi bir türe takma ad vermeye izin verir; yalnızca ad alanlarıyla sınırlı değildir:
using Koordinat = (int X, int Y);
Bu, özellikle demet (tuple) türlerini veya karmaşık genel türleri kısaltmak için kullanışlıdır. Takma adlar dosya kapsamındadır ve derleme zamanında çözülür.
Varsayılan Lambda Parametreleri
Lambda ifadeleri artık varsayılan parametre değerleri alabilir:
var carp = (int a, int b = 2) => a * b;
Bu, temsilci (delegate) türüyle uyumlu olduğu sürece çalışır. Dikkat: varsayılan değerler, çağrı sırasında derleyici tarafından uygulanır; dinamik olarak değiştirilemez.
ref readonly Parametreler
ref readonly, bir değişkenin referansını alır ancak yazmayı engeller. Büyük struct'ları kopyalamadan okumak istediğinizde performans açısından yararlıdır:
public void Yazdir(ref readonly BuyukStruct veri)
{
// veri üzerinde yazma işlemi yapılamaz
}
Güvenlik notu: ref readonly, salt okunurluk garantisi verir; ancak referansın işaret ettiği bellek bölgesinin yaşam süresiyle ilgili sorumluluk hâlâ çağırana aittir. Yerel değişkenlere referans döndürmekten kaçının.
Deneysel Özellikler ve Experimental Özniteliği
.NET 8, deneysel API'leri işaretlemek için System.Diagnostics.CodeAnalysis.ExperimentalAttribute getirir. Bu öznitelikle işaretlenmiş bir API'yi kullanmak derleyici uyarısı üretir. Bu, kararlı olmayan yüzeyleri açıkça ayırt etmeye yarar.
.NET 8 Tarafında Öne Çıkanlar
- Native AOT: Yayımlama sırasında önceden derleme yaparak başlangıç süresini ve bellek kullanımını azaltmayı hedefler. Her uygulama türü için uygun değildir; yansıma (reflection) yoğun kütüphanelerle uyumluluk sınırlı olabilir.
- Performans iyileştirmeleri: Çalışma zamanı ve temel kütüphanelerde çeşitli iyileştirmeler yapılmıştır. Somut kazanımlar iş yüküne göre değişir; ölçüm yapmadan kesin bir sayı vermek yanıltıcı olur.
- Birincil oluşturucular ve koleksiyon ifadeleri, dil tarafında en çok günlük koda yansıyan yeniliklerdir.
Uygulama Adımları
- Projenizin .NET 8'i hedeflediğinden emin olun. Proje dosyasında
TargetFrameworkdeğerininet8.0yapın. - Dil sürümünü kontrol edin. Gerekirse
<LangVersion>12</LangVersion>ekleyin. - Koleksiyon ifadelerini mevcut dizi/liste başlatmalarında deneyin; derleyicinin hedef türü doğru çıkarsadığından emin olun.
- Sınıflarınızda birincil oluşturucu kullanmayı değerlendirin; ancak parametrelerin yaşam süresi ve dışarıya açılması gereken durumları netleştirin.
- Native AOT veya deneysel API'leri kullanmadan önce uyumluluk ve kararlılık durumunu belgeleyin.
Yaygın Hatalar
- Birincil oluşturucu parametresini özellik sanmak: Parametreler otomatik olarak public üye olmaz.
- Koleksiyon ifadesini hedef tür belirtmeden kullanmak: Derleyici türü çıkaramazsa hata verir.
ref readonlyile ömür yönetimini göz ardı etmek: Referansın geçerliliği çağıranın sorumluluğundadır.- Deneysel API'leri üretimde uyarıları bastırarak kullanmak: Bu API'ler geriye dönük uyumluluk garantisi taşımaz.
Güvenlik ve Uyumluluk Notları
- Native AOT, yansıma tabanlı serileştirme veya dinamik kod üretimi kullanan kütüphanelerle çalışmayabilir; bağımlılıklarınızı önceden doğrulayın.
- Deneysel API'ler, sürümler arasında değişebilir veya kaldırılabilir; kritik iş akışlarında bunlara bağımlı olmayın.
ref readonlyve benzeri düşük seviyeli özellikler, bellek güvenliğiyle ilgili sorumluluğu artırır; yanlış kullanım tanımsız davranışa yol açabilir.
Sonuç
C# 12 ve .NET 8, dil söz dizimini sadeleştiren ve çalışma zamanı seçeneklerini genişleten bir dizi yenilik sunar. En yüksek günlük etkiyi birincil oluşturucular ve koleksiyon ifadeleri yaratır; Native AOT ve deneysel API'ler ise daha dar kapsamlı, dikkatli değerlendirme gerektiren alanlardır. Yeni özellikleri benimsemeden önce hedef çerçeve, dil sürümü ve bağımlılık uyumluluğunu doğrulamak, sonradan karşılaşabileceğiniz sürprizleri azaltır.