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 9 of 17 · ~1 min

Generics and Value Types

Generics exist in large part to make the boxing chapter above unnecessary, and the warehouse system's newer audit path proves it directly — replace ArrayList with a generic collection typed to the actual data, and the boxing disappears entirely:

List<StockCount> auditTrailV2 = new List<StockCount>(); // backed by a real StockCount[] — no boxing at all
auditTrailV2.Add(adjustment);

List<object> stillBoxes = new List<object>(); // typed to object — every StockCount added here IS boxed
stillBoxes.Add(adjustment);

Here's the mechanism worth knowing if someone asks why this actually works, rather than just that it does: the CLR doesn't reuse one generic implementation across every type argument indiscriminately. For a value-type argument it compiles and JITs a dedicated version — List<StockCount> and List<int> are two genuinely separate pieces of native code, each one laying its elements out back-to-back with nothing boxed. Swap in a reference-type argument instead — List<Shipment>, List<PriceQuote> — and the runtime stops bothering to specialize at all, because a Shipment reference and a PriceQuote reference are both just a pointer-sized handle underneath, so one compiled version serves every reference type at once. Moving the audit trail off ArrayList and onto List<StockCount> isn't only about catching type mistakes at compile time, then — it's removing a heap allocation from every single write to the log.