Stack vs. Heap in C#
In .NET werden Daten entweder auf dem Stack oder im Heap gespeichert – je nachdem, ob es sich um einen Wert- oder Referenztyp handelt. Der Unterschied hat direkte Auswirkungen auf Speicherverbrauch, Performance und Garbage Collection.
Stack: schnell, kurzlebig, lokal
Der Stack ist ein LIFO-Speicher (Last-In-First-Out). Hier landen lokale Variablen, Parameter und Rückgabewerte. Stack-Allocierung ist extrem schnell, aber limitiert in Größe (z. B. wenige MB).
Beispiel: alle Werttypen werden per Default auf dem Stack gespeichert.
void Demo() { int a = 5; double b = 3.14; bool c = true; // Alles liegt im Stack }
Der Speicher wird automatisch freigegeben, sobald die Methode endet. Kein Garbage Collector nötig.
Heap: dynamisch, langlebig, kontrolliert vom GC
Objekte, die mit new
erzeugt werden, landen im Heap. Auch Arrays, Strings, Klasseninstanzen und alles, was via Referenz manipuliert wird. Speicher wird vom Garbage Collector verwaltet – das macht den Heap langsamer, aber flexibler.
class Person { public string Name; } void Demo() { var p = new Person(); // Objekt im Heap p.Name = "Alice"; }
Die Variable p
liegt im Stack, die Instanz selbst im Heap. Sobald p
nicht mehr referenziert wird, wird das Objekt später vom GC entsorgt.
Boxing: Werttyp → Heap
Boxing passiert, wenn ein Werttyp als object
behandelt wird – etwa bei Listen vom Typ List<object>
, Methoden wie Console.WriteLine(object)
oder Reflection. Dabei wird der Werttyp auf dem Heap verpackt.
int x = 42; object o = x; // Boxing – int wird auf den Heap kopiert
Boxing ist teuer – vermeide es, wenn Performance zählt. Nutze Generics oder explizite Typen statt object
.
Referenztypen: Stack + Heap
Referenzvariablen selbst liegen im Stack, zeigen aber auf ein Objekt im Heap. Die Referenz ist kurzlebig – das Objekt kann langlebig sein.
void Demo() { string s = "Hallo"; // "Hallo" im Heap (intern gepoolt), s im Stack }
Strings sind intern immutable, aber trotzdem Referenztypen.
Stackalloc: Performance-Turbo für kurze Arrays
stackalloc
erzeugt kleine Arrays direkt im Stack – ohne Heap-Allokation und GC. Ideal für Hot Paths oder Signalverarbeitung.
Spanbuffer = stackalloc int[128]; // Kein GC nötig
Span<T>
funktioniert nur innerhalb der aktuellen Methode. Ideal für Parser, Bildverarbeitung, Netzwerkprotokolle.
Garbage Collector und Lebensdauer
Alles, was auf dem Heap liegt, wird vom Garbage Collector verwaltet. Er läuft automatisch, wenn wenig Speicher verfügbar ist oder das System im Leerlauf ist.
- Gen 0: kurzlebige Objekte
- Gen 1: mittel
- Gen 2: langlebige Objekte (z. B. Caches)
Manuelles Freigeben ist nicht nötig – aber: IDisposable
für Ressourcen (Dateien, Streams) trotzdem korrekt verwenden!
Zusammenfassung für Entwickler
- Stack: schnell, klein, lokale Daten
- Heap: flexibel, groß, für Objekte
- Werttyp: meist Stack, außer bei Boxing oder in Objekten
- Referenztyp: Referenz im Stack, Objekt im Heap
- Performance-Tipp: Verwende
stackalloc
für kurze temporäre Puffer