În dezvoltarea componentelor critice de rețea, parsere JSON sau protocoale financiare, alocarea obiectelor pe Heap aduce o penalizare dublă: latența apelării alocatorului de memorie și costul ulterior de curățare al Garbage Collector-ului.
Modificatorul ref struct forțează compilatorul să garanteze contractual că o structură nu poate părăsi niciodată stiva de execuție a firului curent. Începând cu C# 11 și C# 12, structurile ref struct pot declara și câmpuri ref (ref fields), permițând crearea de containere de nivel înalt peste memorie nativă sau felii de date.
// ref struct trăiește exclusiv pe stivă:
public ref struct ParserPachete
{
private ReadOnlySpan<byte> _buffer;
private ref int _pozitieCurenta; // Câmp ref către un întreg extern
public ParserPachete(ReadOnlySpan<byte> buffer, ref int cursor)
{
_buffer = buffer;
_pozitieCurenta = ref cursor;
}
public byte CitesteUrmatorulOctet()
{
byte valoare = _buffer[_pozitieCurenta];
_pozitieCurenta++;
return valoare;
}
}
public class Program
{
public static void Main()
{
byte[] pachet = [0xAA, 0xBB, 0xCC];
int index = 0;
// Parser-ul rulează instantaneu pe stivă:
var parser = new ParserPachete(pachet, ref index);
byte b1 = parser.CitesteUrmatorulOctet();
Console.WriteLine($"Octet citit: 0x{b1:X2}, Index actualizat: {index}");
}
}
Restricții Impuse de Compilator pentru Siguranța Memoriei
| Restricție Compilator | Motivație Tehnică |
|---|---|
Nu poate fi boxată (nu poate fi convertită la object sau ValueType). |
Boxing-ul ar forța copierea structurii pe Heap, încălcând garanția de stivă. |
| Nu poate fi câmp într-o clasă normală. | Clasele trăiesc pe Heap; o clasă nu poate deține o referință către o stivă care poate dispărea. |
Nu poate fi folosită în metode async. |
Metodele asincrone generează o mașină de stări pe Heap care poate supraviețui apelului inițial. |