Span<T> ve Memory<T>, bitişik bellek (diziler, dizeler, arabellek) ile çalışmak için modern .NET türleridir — tahsisler veya kopyalamalar olmadan verimli bir şekilde. Yeni kopyalar oluşturmak yerine mevcut belleğe bir görünüm sağlayarak yüksek performanslı kod etkinleştirir, GC baskısını azaltır.
Sorun: dilim oluşturma kopyalar yaratır (tahsisler)
// ❌ Substring allocates a NEW string (copies the data) — GC pressure in hot paths
string text = "Hello, World";
string sub = text.Substring(7); // allocates a new "World" string
// ✅ Span — a VIEW into the existing memory, NO allocation, NO copy
ReadOnlySpan<char> span = text.AsSpan(7); // "World" — points into the original
Substring veya dizi dilimi gibi işlemler yeni nesneler tahsis eder ve veri kopyalar. Span<T> bunun yerine mevcut belleğe bir görünüm (işaretçi + uzunluk) sağlar — dilim oluşturma hiçbir şeye mal olmaz, hiçbir şey tahsis etmez.
Span<T> — sıfır kopyalama dilimi
int[] numbers = { 1, 2, 3, 4, 5 };
Span<int> slice = numbers.AsSpan(1, 3); // {2, 3, 4} — a VIEW, no copy
slice[0] = 99; // modifies the ORIGINAL array (it's a view)
// parse without allocating substrings
ReadOnlySpan<char> input = "123,456".AsSpan();
int first = int.Parse(input.Slice(0, 3)); // parse a slice, no substring allocation
Span<T>, tahsis etmeden diziler/dizeler/arabellek işlemek ve işlemek için dilim oluşturmanıza izin verir — sıcak yollar (ayrıştırma, serileştirme, büyük veri işleme) için çok önemlidir.
Kısıtlama: Span yalnızca yığın kapsamında
Span<T> is a ref struct — it can ONLY live on the stack (not on the heap, not in
async methods, not as a class field). This guarantees safety but limits where it's used.
Memory<T> — depolanabilir/eşzamansız kullanılan Span
// Memory<T> is like Span<T> but CAN be a field / used across await (heap-storable)
async Task ProcessAsync(Memory<byte> buffer) // works in async (Span<T> can't)
{
await stream.ReadAsync(buffer);
Span<byte> span = buffer.Span; // get a Span from it when you need to process
}
Memory<T>, görünümü depolemeniz veya eşzamansız kodda kullanmanız gereken senaryolar için Span<T> tamamlar (Span<T>'in yalnızca yığın kapsamı doğası burada işe yaramaz).
Neden önemli
Span<T> ve Memory<T>, yüksek performanslı, tahsisiz kod için modern .NET'in önemli özellikleridir ve bunları anlamak, performans açısından kritik uygulamalar için değerli üst düzey bilgidir.
Temel değerleri, yeni kopyalar tahsis etmek yerine mevcut belleğe bir görünüm sağlayarak bitişik bellek (diziler, dizeler, arabellek) ile verimli çalışmayı etkinleştirmekdir — tahsisler GC baskısı oluşturur ve sıcak yollarda (ayrıştırma, serileştirme, büyük veri işleme, ağ arabellekleri) tahsislerden kaçınmak performansı önemli ölçüde artırır.
Normalde tahsis yapan işlemler (Substring, dizi dilimi) span ile tahsisiz olarak yapılabilir, bellek kullanımını ve GC yükünü azaltır.
Span<T> (diziler/dizeler/arabellek için sıfır kopyalama dilimi), yalnızca yığın kapsamı kısıtlaması (bu bir ref struct'tır, bu nedenle bir sınıf alanı veya eşzamansız metotlarda kullanılamaz — önemli bir sınırlama) ve Memory<T> (depolanabilir ve eşzamansız kodda kullanılabilen tamamlayıcı) anlamak, yüksek performanslı C# yazmak için önemlidir.
Bu türler, modern .NET'in kendi performans açısından kritik kodunda yaygın olarak kullanılır ve giderek artan şekilde tahsisiz, verimli bellek işlemenin önemli olduğu kitaplık ve uygulamalarda kullanılır.
Gündelik iş mantığı için gerekli olmasa da, Span<T>/Memory<T> — ne yaptıkları (tahsisiz bellek görünümleri), neden yardımcı oldukları (azaltılmış tahsisler ve GC baskısı) ve kısıtlamaları — performansa duyarlı C# geliştirme (ayrıştırma, serileştirme, yüksek aktarım hızı sistemleri), yüksek verimli .NET kodu yazabilen geliştiricileri ayırt etmek ve performans odaklı üst düzey roller için ilgili bir konudur.
