I'm writing a program that is very sensitive to garbage collection so I'm trying to avoid allocating to the heap after initialization.
In the example below, calling Run() will allocate to the heap when it calls DoThing() on any of the elements in the list. This is due to things being backed by structs (Thing1, Thing2, etc).
I want to avoid this allocation, but I also don't want to have to specify multiple lists (one per struct type). Is there a way to do this cleanly and efficiently?
interface IThing
{
void DoThing();
}
struct Thing1 : IThing
{
public void DoThing(){}
}
struct Thing2 : IThing
{
public void DoThing(){}
}
List<IThing> things;
void Initialize()
{
things = new List<IThing>();
things.Add(new Thing1());
things.Add(new Thing2());
}
void Run()
{
foreach(IThing thing in things)
{
thing.DoThing(); //this allocates to the heap due underlying type being a struct
}
}
You can see in the image below that there are memory allocations from Line 38.


readonly structs right?List<Thing>will be backed by an array of structures. This array would still be stored on the heap. Though it would be a contiguous block of memory. The only way to avoid that is tostackallocaSpan<Thing>.