---
title: "Yes you can create classes on the stack!"
description: "In this article we will create a class, aka a reference type on the stack, and therefore don't use any managed memory!"
updated: 2023-11-01
tags: ["C#", ".NET"]
canonical: "https://steven-giesel.com/blogPost/74cc8abc-b6e3-4cb0-ba98-9c92f9a5a4d2/yes-you-can-create-classes-on-the-stack"
---

# Yes you can create classes on the stack!

In this article we will create a class, aka a reference type on the stack, and therefore don't use any managed memory!

Here is the "simple" code:
```csharp
public record MyClass(int Number);

var typeHandleValue = typeof(MyClass).TypeHandle.Value;
var size = Marshal.ReadInt32(typeHandleValue, 4);
var mem = stackalloc byte[size];
*(IntPtr*)mem = typeHandleValue;
var instance = Unsafe.AsRef<MyClass>(&mem);
```

The whole idea is to create a pointer to the type handle of the class and then use the pointer to create an instance of the class on the stack.
We are using `stackalloc` to allocate the memory on the stack and then use `Unsafe.AsRef` to create a reference to the allocated memory.
Is it useful? Probably not, but it is possible! And that is all I wanted to show. 

The "main issues" with this approach:
 * You are not calling any constructor
 * Your fields are all "uninitialized" - in the sense that integers are not necessarily 0
 * The size has to be static. You can't increase or decrease the size.

So, all in all: Yes, this is a class coated as a struct! With all its downside and almost no upsides.

Here is a small benchmark:

```csharp
[MemoryDiagnoser]
public class Benchmarks
{
    private static readonly IntPtr TypeHandleValue = typeof(MyClass).TypeHandle.Value;
    private static readonly int Size = Marshal.ReadInt32(TypeHandleValue, 4);

    [Benchmark]
    public unsafe MyClass OnStack()
    {
        var mem = stackalloc byte[Size];
        *(IntPtr*)mem = TypeHandleValue;
        return Unsafe.AsRef<MyClass>(mem);
    }

    [Benchmark]
    public MyClass OnHeap() => new MyClass(0);
}

public record MyClass(int Number);
```

With the following result:
```no-class
|  Method |      Mean |     Error |    StdDev |   Gen0 | Allocated |
|-------- |----------:|----------:|----------:|-------:|----------:|
| OnStack | 0.6014 ns | 0.0136 ns | 0.0127 ns |      - |         - |
|  OnHeap | 1.1356 ns | 0.0270 ns | 0.0252 ns | 0.0029 |      24 B |
```

As we can see, `OnStack` has a better runtime and doesn't allocate any memory. And `Number` will also be initialized to something - not necessarily 0. But hey, I never mentioned that the executed program is correct!