În programarea tradițională, parsarea unui fișier mare CSV sau JSON folosind metode precum `string.Substring()` sau `string.Split()` genera zeci de mii de obiecte mici de tip string în memoria Heap, declanșând cicluri frecvente și costisitoare ale colectorului de gunoi (Garbage Collector).
Tipurile revoluționare Span<T> și ReadOnlySpan<T> reprezintă o ‘fereastră’ (view) directă peste o regiune de memorie contiguă — indiferent dacă acea memorie se află pe Stivă (Stack), pe Heap sau în memorie neadministrată nativă.
Operația de decupare (slicing) a unui `ReadOnlySpan
Sintaxă, opțiuni și concepte cheie
| Opțiune / Concept | Descriere practică |
|---|---|
Span |
Tip ref struct alocat exclusiv pe stivă ce oferă acces de citire și scriere la memorie contiguă. |
ReadOnlySpan |
Înlocuitorul modern de înaltă performanță pentru operațiile de decupare și căutare în string-uri. |
Memory |
Alternativa sigură la Span care poate fi stocată în câmpuri de clase și utilizată în metode asincrone (`async/await`). |
Zero Garbage Collection Pressure |
Beneficiul eliminării totale a alocărilor pe Heap pe durata parsării masive de date. |
Exemple practice și cod
Exemplul 1: Parsarea unei linii de log fără nicio alocare de memorie pe Heap
Cum se extrag datele folosind ReadOnlySpan în loc de Substring.
// Linie de intrare dintr-un fișier de log:
string logLine = "2026-10-24 14:30:15 [ERROR] Conexiune baza de date refuzata";
// Transformăm stringul într-un span fără alocare:
ReadOnlySpan span = logLine.AsSpan();
// Extragem componentele exclusiv prin slicing (pointer + length, zero alocări):
ReadOnlySpan dataOra = span.Slice(0, 19);
ReadOnlySpan nivel = span.Slice(21, 5);
// Comparare directă fără alocare de string nou:
if (nivel.SequenceEqual("ERROR"))
{
Console.WriteLine($"Eroare detectată la data: {dataOra.ToString()}");
}
Rezultat & Impact
Viteză de execuție de până la 10x mai mare cu presiune zero pe Garbage Collector.
Greșeli frecvente și bune practici
- Încercarea de a stoca un `Span
` ca un câmp într-o clasă obișnuită sau utilizarea lui într-o metodă `async`; fiind un `ref struct`, Span nu poate părăsi stiva (folosiți `Memory ` pentru scenarii asincrone). - Conversia prematură a fiecărui fragment înapoi în `string` prin apelul `.ToString()`, ceea ce anulează complet beneficiul de alocare zero.