11.10. Memory Footprint

Generic types don't just perform better than non-generic types—they also consume less memory. Let's stick with the theme of ArrayList versus List<T> that was used in the previous set of examples. When you use an ArrayList to hold value types, these value types get boxed and placed on the heap. For each of these boxed items on the heap, there must also be a corresponding object reference added to the ArrayList. The overhead of these references and the heap allocations do not end up being trivial for any reasonably sized ArrayList.

In contrast, the List<T> is able to do away with all this added overhead. Each value type it holds is placed directly into an internal array that holds that value in its native representation. That means no heap allocation and no references.

A nonscientific look at the run-time memory profile of ArrayList and List<T> suggests that the difference in memory consumption is actually quite profound. I created a test that populated both data containers with a collection of 200,000 integers. The ArrayList required 39MB to represent these values whereas the List<T> instance appeared to only consume 16MB. That's a difference of 244 percent.

So, with all the attention focused on type safety and expressiveness, it may end up being the case that performance actually represents the single most significant advantage offered by generics. Performance gains of this magnitude are simply too compelling to ignore.

Get Professional .NET 2.0 Generics now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.