I’m wondering whether boxing a value type in an object is a special case or whether the “box” constructed by .NET becomes garbage (that the GC has to collect) after any references to it are dropped.
For example, StringBuilder.AppendFormat() has these overloads:
StringBuilder.AppendFormat(string format, object arg0);
StringBuilder.AppendFormat(string format, object arg0, object arg1);
StringBuilder.AppendFormat(string format, object arg0, object arg1, object arg2);
StringBuilder.AppendFormat(string format, params object[] args);
Having those additional overloads for calls with 3 or fewer arguments might indicate that boxing indeed is a special case (or that it pays off, from a performance point-of-view, to avoid array construction).
Theoretically, using plain old reference counting, possibly with a pool of reusable boxes would be a valid implementation because there can be no references from one box to another, only from .NET objects to a box.
First off, just to clarify: creating an array of object references is not boxing. “Boxing” is a term with a very specific meaning in .NET, and I think it’s worth sticking to it.
Boxing does create garbage – or rather, each time you box, it creates a new object which is likely to eventually become garbage. (It doesn’t have to become garbage – you might have a reference to that object for the rest of the app’s lifetime; it’s just pretty rare.)
However, you could have a cache for boxing purposes. Indeed, Java does for small numbers. If you write:
then that’s guaranteed to print
true.However, that’s just a small cache for a fixed set of types – it’s not a general purpose cache. You need to balance the pain of having a general cache with weak references (not reference counting – the GC mechanism in .NET just isn’t reference counted, and you couldn’t really introduce that just for boxed values) would almost certainly hurt performance more than the small cost of boxing creating garbage.
.NET could have taken the same approach as Java and boxed some values of some types, but I’m not sure it’s worth the extra conceptual baggage – especially when the platform supports custom value types (which Java doesn’t).
It’s probably worth noting that since .NET 2.0, boxing is somewhat rarer than it used to be. It happens a fair amount in data binding and reflection, but it’s less common in plain old data manipulation now.