The CLR has no restrictions that each class field must have the same storage type. Only instance members fall into the GC heap. Static elements are allocated on the bootloader heap. Or in streaming local storage when the field has the [ThreadStatic] attribute. This, of course, imposes a contract on the fact that the static member is shared by each instance of the class object.
A very simple btw implementation, jitter allocates storage and knows the address of the field. Thus, any load and stores directly use the address of the variable. No extra dereferencing pointers, very effective.
So, no, there is no need for a box at all, a static int will only take 4 bytes.
If you want to see this for yourself, use the Debug + Windows + Disassembly window. Shows the machine code, you will see it using the address of the variable directly. This will be a different address each time you run a program that is against the law.
source share