1

I have been reading a book and encountered a statement, that generics allow the programmer to avoid need of boxing and unboxing when using e.g. Stack.

I think it is not entirely correct as the Stack (not generic) could hold just reference type variables and then there is just casting, no boxing.

EDIT: AFAIK, boxing relates to only value types to object conversion. Is that correct or am I missing something?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Mocco
  • 1,183
  • 2
  • 12
  • 25
  • Do you mean the `Stack` class or the `Stack<>` generic class? They are different. – Nick Mar 25 '11 at 09:59
  • 1
    Yes, that's correct. Boxing is only relevant when you're dealing with value types. Most of the answers so far miss the point. – Cody Gray - on strike Mar 25 '11 at 10:07
  • Similar to: http://stackoverflow.com/questions/2421568/generics-vs-boxing – Nick Mar 25 '11 at 09:58
  • To elaborate on Cody Gray's comment with a specific example: If you store a string in a non-generic collection, the collection stores a reference to the string, and that reference is of type object. (The same is true for all reference types, not just string.) This is not the same thing as boxing. Boxing involves creating an object instance containing a copy of a value type's value, for the purpose of serving as a target of an object reference (which, in this case, the collection will hold). – phoog Mar 29 '11 at 00:01

2 Answers2

3

If you have a Stack<SomeReferenceType> no (un)boxing will occur simply because references never need to be boxed. References are the "normal" way types work in .NET - object is after all a reference type.

Edit: Your clarified question makes clear you're talking about the non-generic variant of Stack. You are correct in saying that this variant does not need to box and unbox reference types, since reference types are never boxed (and indeed cannot be boxed). It is also correct that if you place an instance of a subclass of object into the Stack, then when you take the item out and try to use an aspect of the instance (which is not general to all objects), then you will need to cast to the subclass.

Note that (for reference types) though we speak of 'casting' to object conceptually, this doesn't correspond to an actual operation; upcasting (to object or any other superclass) is free. It's in the downcast that the machine needs to verify that the downcast is valid. So merely filling a non-generic variant of Stack with instances of reference types is efficient; overhead only occurs when extracting from the Stack and casting to a more specific type.

Why you should prefer the generic collections.

Although (down)casting is fairly cheap, it's not free. Even for reference types, if you need to extract the values again, expect the generic collections to outperform their non-generic counterparts slightly. However, even when you're (as usual) not interested in a few CPU cycles, the generic collections are preferable because they help you spot bugs sooner: if you accidentally add an item of the wrong type to a non-generic list, you won't get a warning nor will you see an error until you extract and use that value, which may be much later (or even never) and in a different code file or even different assembly. Debugging such errors is a real hassle, particularly if you code has a bunch of layers and the error isn't in the layer directly accessing the collection.

By contrast, a generic collection won't even compile if you attempt to add a value of an incorrect type. And even if you need to implement a type-unsafe interface and the compiler can't catch the error, you'll still have the advantage that an InvalidCastException is thrown when you add the item to the collection (near the root cause of the bug) rather than after extraction (far from the root cause of the bug). There will be bugs in code, and you want to find them quickly and cheaply, rather than get odd exceptions in seemingly unrelated code.

Really, the only reason to ever use the non-generic collections anymore is to inter-operate with legacy API's that require their use.

Eamon Nerbonne
  • 47,023
  • 20
  • 101
  • 166
1

The problem is that the Stack class stores the objects you put into it as object. This means, every time you put something on the stack, it will be boxed into an object and every time, you want to use on object from the stack, you need to unbox it again, to get the correct type.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • The thing is that boxing process involving ONLY value types. – Mocco Mar 25 '11 at 09:59
  • I think he might be talking about the generic `Stack<>` class. – Nick Mar 25 '11 at 10:00
  • @Mocco: Yes, you are right. But what makes you think, you can't use value types in a stack? Maybe I misunderstood your question... – Daniel Hilgarth Mar 25 '11 at 10:01
  • Thanks. My question was just whether the book is correct in statement suggesting that boxing happens every time you add an object to Stack class. I thought it was wrong as it happens only for value types. – Mocco Mar 25 '11 at 10:03