Skip to main content
CodeOath
← All posts

C#64 min total · 17 parts

C# Fundamentals: Value Types, Reference Types, Boxing, and the Type System

Part 8 of 17 · ~1 min

Boxing and Unboxing

Every stock adjustment the pick station makes gets written to an audit trail — a requirement that predates this system by several years, back when the warehouse's tooling was built entirely around System.Collections.ArrayList, long before generics existed in the language. That old audit log still exists, and feeding a StockCount into it means crossing into boxing territory: wrapping a value type in a heap-allocated object so it can sit in a collection that only knows how to hold object.

ArrayList auditTrail = new ArrayList();
var adjustment = new StockCount { Sku = "WDG-100", OnHand = 41 };
auditTrail.Add(adjustment);       // boxes the struct — a new heap object wrapping a COPY of it

var replay = (StockCount)auditTrail[0]; // unboxing — copies the value back out

That box captures a snapshot, taken the instant Add ran — which is worth confirming rather than assuming, because it's the detail that actually matters here:

adjustment.OnHand = 999;                          // mutate the original AFTER boxing it
var reread = (StockCount)auditTrail[0];
Console.WriteLine(reread.OnHand);                 // 41 — the box never saw the later change

None of that comes for free — a box is a genuine heap allocation, and creating one means copying the struct's entire contents into it — and the part that trips people up is how easily it happens without anything on the line announcing it:

Console.WriteLine("adjusted: " + adjustment.OnHand); // OnHand is boxed here to be treated as an object

Every value written to auditTrail across a busy shift is its own separate heap allocation and its own bit of work for the garbage collector to clean up later — invisible in a five-line demo, and a genuine cost in a system logging thousands of adjustments a day.