14

So I understand what boxing and unboxing is. When's it come up in real-world code, or in what examples is it an issue? I can't imagine doing something like this example:

int i = 123;
object o = i;           // Boxing
int j = (int)o;     // Unboxing

...but that's almost certainly extremely oversimplified and I might have even done boxing/unboxing without knowing it before.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
Chris
  • 4,030
  • 4
  • 47
  • 76
  • I agree with you. From everything I've read on the subject I just don't get the point. Must be missing something :) – KP. Dec 22 '09 at 21:03

8 Answers8

35

It's much less of an issue now than it was prior to generics. Now, for example, we can use:

List<int> x = new List<int>();
x.Add(10);
int y = x[0];

No boxing or unboxing required at all.

Previously, we'd have had:

ArrayList x = new ArrayList();
x.Add(10); // Boxing
int y = (int) x[0]; // Unboxing

That was my most common experience of boxing and unboxing, at least.

Without generics getting involved, I think I'd probably say that reflection is the most common cause of boxing in the projects I've worked on. The reflection APIs always use "object" for things like the return value for a method - because they have no other way of knowing what to use.

Another cause which could catch you out if you're not aware of it is if you use a value type which implements an interface, and pass that value to another method which has the interface type as its parameter. Again, generics make this less of a problem, but it can be a nasty surprise if you're not aware of it.

Sperick
  • 2,691
  • 6
  • 30
  • 55
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 7
    "I think I'd probably say that reflection is the most common cause of boxing in the projects I've worked on" -- this, of course, will depend heavily on the kind of projects. For example, if you work with WPF or Silverlight, boxing will occur *all the time* as you work with value converters (IValueConverter takes and returns object), dependency properties (DependencyObject.GetValue and SetValue return and take object), etc. – itowlson Dec 22 '09 at 21:10
  • +1 For interface implemented on a value type - that is a sneaky one :) – Andrew Hare Dec 22 '09 at 21:13
  • @itowlson: Those are great examples - mind if I add them to my answer? – Jon Skeet Dec 22 '09 at 21:23
  • Is it safe to say that boxing is "casting something to an object" and unboxing is "casting it back to its type"? – JYelton May 28 '10 at 16:55
  • 1
    @JYelton: I think that's a bit to general *and* too specific. Firstly, it only applies to value types. Secondly, it happens whenever you convert a value type value to a reference type value: an interface, `Object`, `ValueType` or `Enum`. – Jon Skeet May 28 '10 at 17:23
  • Thanks, I'm trying to understand the concept and this question thread helped. :) – JYelton May 28 '10 at 18:57
8

Boxing (in my experience) usually occurs in these cases:

  • A value type is passed to a method that accepts an argument of type Object.
  • A value type is added to a non-generic collection (like an ArrayList).

Other times you can see boxing and unboxing is when you use reflection as the .NET framework's reflection API makes heavy use of Object.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • 1
    We need to note: int (Int32) is a subclass of the abstract class ValueType, which is a subclass of Object. – Gabriel McAdams Dec 22 '09 at 21:09
  • I wouldn't say it's a "subclass" - it's not a *class* at all. It inherits from (or derives from) `ValueType`. The C# and CLI spec use slightly different terminology on this front, which doesn't help matters. – Jon Skeet Dec 22 '09 at 21:10
5

Boxing/unboxing occurs when a value type (like a struct, int, long) is passed somewhere that accepts a reference type - such as object.

This occurs when you explicitly create a method that takes parameters of type object that will be passed value types. It also comes up when you use the older non-generic collections to store value types (typically primitives).

You will also see boxing occuring when you use String.Format() and pass primitives to it. This is because String.Format() accepts a params object[] - which results in boxing of the additional parameters in the call.

Using reflection to invoke methods can also result in boxing/unboxing, because the reflection APIs have no choice but to return object since the real type is not known at compile time (and the Reflection APIs cannot be generic).

The newer generic collections do not result in boxing/unboxing, and so are preferable to the older collections for this reason (eg ArrayList, Hashtable, etc). Not to mention they are typesafe.

You can avoid boxing concerns by changing methods that accept objects to be generic. For example:

public void string Decorate( object a ) // passing a value type results in boxing
{
   return a.ToString() + " Some other value";
}

vs:

public void string Decorate<T>( T a )
{
   return a.ToString() + " some other value";
}
LBushkin
  • 129,300
  • 32
  • 216
  • 265
3

Here is a really nasty one :)

SqlCommand cmd = <a command that returns a scalar value stored as int>;

// This code works very well.
int result = (int)cmd.ExecuteScalar();

// This code will throw an exception.
uint result = (uint)cmd.ExecuteScalar();

The second execute fails because it tries to unbox an Int32 into an UInt32 which is not possible. So you have to unbox first and than cast.

uint result = (uint)(int)cmd.ExecuteScalar();
Alex
  • 1,997
  • 1
  • 16
  • 31
1

Boxing and unboxing is really moving from value type to reference type. So, think of it as moving from the stack to the heap and back again.

There certainly are cases where this is relevant. The inclusion of generics in the 2.0 framework cut a lot of common boxing cases out of practice.

marcc
  • 12,295
  • 7
  • 49
  • 59
1

It happens all the time when people do not know what the implications are, simply don't care or sometimes one cannot help but accept boxing as the lesser evel.

Strongly typed datarows will box/unbox pretty much all the time when you access a value-type property. Also, using a value type as an interface reference will box it as well. Or getting a delegate from an instance method of a value type. (The delegate's target is of type Object)

Robert Giesecke
  • 4,314
  • 21
  • 22
-1

Since the advent of strongly-typed lists and dictionaries using generics with C# 2.0 (Visual Studio 2005), I think the importance of keeping boxing/unboxing in mind have been amazingly minimized. Add to that nullable types (int?, etc.) and using the null coalescing operator (??) and it really shouldn't be much of a concern at all and would likely not see it in any code that's not 1.1 Framework or earlier.

Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
  • 2
    No, in generics there's a lot more boxing going on than most people would expect. C# will emit .box when you check unconstraint Ts against null. – Robert Giesecke Dec 22 '09 at 21:12
  • I agree with that - but that is the developer's decision to do when implementing a generic method/class. From a framework perspective, the generic collections allow the consumer to forego the boxing/unboxing scenario. When I code the scenario you describe, my unconstrained T would be compared against default(T), not null. If I *really* need a check against null, T better be constrained to a reference type. – Jesse C. Slicer Dec 22 '09 at 21:50
  • "in any code that's not 1.1 Framework or earlier" - what about a simple string.Format("My number is {0}", 123)? – Alex Dec 22 '09 at 22:51
  • I give you that will indeed box (but not unbox), but if you are performing such an operation in a program's hotspot where boxing and/or unboxing have an obvious adverse effect on performance, then I daresay your system organization or algorithm is faulty. – Jesse C. Slicer Dec 22 '09 at 23:06
  • @Robert Giesecke : This should be a full answer, not some comment lost somewhere in the page... :-) ... – paercebal Jan 06 '12 at 14:27
  • That time when you say the same thing as Jon Skeet, but unfortunately posts one minute later and then get downvoted a dozen years later as opposed to his almost three dozen upvotes. – Jesse C. Slicer Oct 20 '21 at 21:12
-2

"The type parameter for an ArrayList must be a class, not a primitive type, so Java provides wrapper classes for the primitive types, like "Integer" for int, "Double" for double, etc.

For more explanation:

An array is a numbered sequence of elements, and each element acts like a separate variable."

Java provides a special syntax for "for" loops over the elements of arrays (and other collection types in Java). The simplified syntax is called a "for-each" loop. For example, the following statement prints each String in an array called "words".

for (String word : words) System.out.println(word);

An array has a number of elements that are set when the array object is created and cannot be changed. Java provides the "ArrayList" class for the functionality of a dynamic array, an array that can change in size. ArrayList is an example of a parameterized type, a type that depends on another type." Eck (2019)

References : Introduction to Programming Using Java, Eck (2019) describes as follows in Chapter 7