C# STRING İŞLEMLERİ

Üç boyutlu immutable string zinciri, büyüyen bloklar ve altta hayalet kopyalar, mor tonlarda

Eski bir kodun içinde şu satırı görürsün: bir döngünün her turunda result += line. Dosya bir milyon satırlıksa uygulama dakikalarca asılı kalır, profiler GC pressure'ı kırmızıya boyar. Geliştirici suçu döngüye yıkar, oysa asıl sebep daha derinde — C#'ta string değiştirilemez. Her birleştirme yeni bir nesne yaratır, eskisini çöp toplayıcının kapısına bırakır. Bu yazı, C# string işlemlerini günlük geliştirme akışında karşılaşılan tuzaklarla birlikte ele alır: metin birleştirme, ayrıştırma, karşılaştırma, kültür duyarlılığı ve StringBuilder'ın gerçekten ne zaman devreye gireceği.

String Neden Değişmez

C#'ta string aslında System.String sınıfının takma adıdır. Bu sınıf immutable'dır; bir kez oluşturulduktan sonra içeriği değiştirilemez. s = s + "!" yazdığında C# değişkenin bellekteki içeriğine bir karakter eklemez — yeni bir string nesnesi oluşturur, eski nesneye olan referansı bırakır ve s'yi yeni nesneye yönlendirir. Eski nesne çöp toplayıcının sıradaki adayıdır.

Bu tasarım kararı bilinçlidir. Immutable string'ler thread-safe'dir, hash table anahtarı olarak güvenlidir, paylaşılan referanslarla güvenle dağıtılabilir. Bedeli: her "değişiklik" yeni nesne anlamına gelir. Tek bir s + " " + t ifadesinde bu sorun yok; bir döngü içinde tekrar eden birleştirmede ise bellek hızla şişer. Ayrıntılı arka plan için Microsoft'un C# dil kılavuzu string ile ilgili tüm BCL üyelerini barındırır.

Temel İşlemler — Birleştirme, Bölme, Değiştirme

Günlük geliştirmede en sık çağrılan string metotları aslında bir avuçtur. Hepsi System.String üzerinde tanımlıdır ve dönüş değeri olarak yeni bir string üretir.

  • Concat ve + — iki ya da daha fazla string'i birleştirir
  • Substring(start, length) — belirli bir bölümü kopyalar
  • Replace(eski, yeni) — tüm geçişleri değiştirir
  • Split(ayraç) — string'i diziye böler
  • Join(ayraç, dizi) — diziyi tek string'e dönüştürür
  • Trim, TrimStart, TrimEnd — kenar boşluklarını temizler
  • ToUpper, ToLower — büyük/küçük dönüşümü (kültür uyarısı aşağıda)
  • Contains, StartsWith, EndsWith, IndexOf — arama ve kontrol

Format işlemleri için üç yol vardır: klasik string.Format("{0} {1}", a, b), modern string interpolation ($"{a} {b}") ve birleştirme operatörü +. Üçü de derlenmiş çıktıda benzer IL üretir; ancak interpolation okunabilirlik açısından açık ara önde. string.Format hâlâ resource dosyasından gelen şablonlar için anlamlıdır çünkü format string'i çalışma zamanında değişkendir.

Üç boyutlu StringBuilder buffer ve atılmış string kümesi karşılaştırması, X işareti ve bin formu

Karşılaştırma ve Kültür Tuzağı

String karşılaştırma C#'ta deneyimsiz geliştiricinin tökezlediği bir yerdir. Üç yaygın yol vardır ve her birinin davranışı farklıdır.

  1. == operatörü — referans değil içerik karşılaştırır (string için özel overload var). Kültür ayarına duyarlıdır.
  2. Equals(other) — örnek metot, varsayılan olarak ordinal karşılaştırır
  3. string.Equals(a, b, StringComparison.OrdinalIgnoreCase) — açıkça niyet beyan eden tercih edilen yol

Tipik tuzak Türkçe lokalde "İ" ve "i" harfleridir. "İSTANBUL".ToLower() çağrısı Türkçe kültürde "istanbul" üretir, invariant kültürde "i̇stanbul" (noktalı küçük i) üretir. Veritabanı sorgusu, dosya yolu, kullanıcı adı kontrolü gibi kültürden bağımsız olması gereken yerlerde her zaman StringComparison.OrdinalIgnoreCase kullanılır. Kullanıcıya gösterilen sıralama ya da arama gibi kültüre duyarlı yerlerde StringComparison.CurrentCulture tercih edilir.

Pratik kural: bir karşılaştırma yazarken StringComparison argümanı eklemeden geçme. IDE genellikle "use StringComparison" hata mesajı verir; bu uyarıyı bastırmak yerine doğru karşılaştırma türünü seç.

StringBuilder Ne Zaman Devreye Girer

Geliştiriciler arasında dolaşan "her birleştirmede StringBuilder kullan" tavsiyesi yanlıştır. Birkaç string'i tek satırda birleştirirken + hem okunaklıdır hem de derleyici onu zaten string.Concat'e çevirir. StringBuilder esas olarak şu durumlarda faydalıdır:

  • Belirsiz sayıda parçayı bir döngü içinde birleştirme
  • Çok uzun bir metnin parça parça oluşturulması (örneğin CSV/JSON üretimi)
  • Önceden boyutu kestirilebilen tampona yazma (kapasite parametresi geçilebilir)

Tipik kullanım şöyledir: var sb = new StringBuilder(); foreach (var line in lines) sb.AppendLine(line); return sb.ToString();. StringBuilder dahili olarak büyüyebilen bir tampon tutar; Append çağrıları yeni string nesnesi oluşturmaz, var olan tampona ekler. Milyon satırlık birleştirmede fark milisaniyeden onlarca saniyeye uzanabilir.

Eşik nedir? Genel kural: üç birleştirme veya daha fazlasını döngüde yapıyorsan StringBuilder'a geç. C# diline ve .NET ekosisteminin temel sınıflarına yapılandırılmış biçimde girmek isteyenler için kapsamlı C# eğitimi string'den koleksiyonlara, LINQ'tan async/await'e kadar tüm temel kavramları pratik örneklerle ele alır.

Üç boyutlu kültür karşılaştırma kartları ve interpolation parantez sembolü, mor tonlarda

Modern C# String Özellikleri

Son birkaç dil sürümü string tarafına ciddi yenilikler getirdi. Bunların çoğu kod okunabilirliğini ve performansını birlikte iyileştirir.

String interpolation (C# 6+) — $"Merhaba {ad}, bakiyen {tutar:C2}" şeklinde inline ifade ve format. Format spesifikatörü doğrudan ifadenin sonuna yazılır.

Raw string literals (C# 11+) — üç ya da daha fazla tırnakla başlayan, escape gerektirmeyen blok literal'lar. JSON, SQL, regex gibi içerikleri kaçış karakterleri olmadan yazmak için ideal.

Span<char> ve ReadOnlySpan<char> — string'in bir bölümüne kopyasız erişim. "merhaba dünya".AsSpan(0, 7) ile yeni nesne yaratmadan parça üzerinde çalışılır. Yüksek performanslı parser'lar bu yapıyı yoğun kullanır.

String.Create ve handler tipleri — interpolation içeride özelleştirilebilir, böylece logger gibi yerlerde format string yalnızca log seviyesi yeterliyse hesaplanır. .NET 6 ile gelen ILogger interpolation desteği bu altyapıyı kullanır.

Pratik İpuçları

Günlük çalışmada sık sık karşılaşılan birkaç ufak nokta:

  • Boş kontrol için string.IsNullOrEmpty(s) veya yalnızca boşluk içeriyorsa string.IsNullOrWhiteSpace(s)
  • Split ile gelen boş elemanları atlamak için StringSplitOptions.RemoveEmptyEntries seçeneği
  • Sayıya çevirirken int.TryParse kullan; int.Parse hatada exception atar
  • Dosya yolu birleştirmede + değil Path.Combine kullanılır
  • URL parametresi birleştirirken UriBuilder veya Uri.EscapeDataString tercih edilir
  • Çok satırlı metin tutarken raw literal okunabilirlik açısından kaçışlı string'e göre kazançlıdır

String işlemleri C#'ın en temel ama en yanlış kullanılan alanlarından biri. Birkaç prensibi içselleştirdiğinde — değişmezlik, kültür duyarlılığı, ne zaman StringBuilder — kodun hem okunaklı hem hızlı kalır.