Boxing and Unboxing

Possible duplicate:
What is boxing and unboxing and what are the trade-offs?

Good. I understand the basic concept of what happens when you insert and unpack.

The box pushes the value type (stack object) into the System.Object object and stores it on the heap. Unbox unpacks this object on the heap, holding this value type, and throws it back onto the stack so that it can be used.

Here is what I do not understand:

  • Why do this ... concrete examples in the real world

  • Why are generics so effective? They say because Generics do not need to be unpacked or inserted into a box, fine .. I don’t understand why ... what’s behind this in generics

  • Why generics are better than other types say. Say, for example, other collections?

so overall I don’t understand this in the application in the real world in terms of code, and then I continue on how it improves the generics ... why it should not do any of this in the first place when using Generics.

+4
source share
8 answers
  • This must be done because at the IL level there are different instructions for value types than for reference types ( ldfld vs ldflda ), check the disassembler for the method that calls someValueType.ToString() vs someReferenceType.ToString() and you will see that the instructions different).

    These instructions are incompatible, so when you need to pass a value type to a method as an object, you need to wrap this value in a reference type (box). This is unlikely because the runtime needs to copy the value type and then create a new box type in order to pass a single value.

  • Generics are faster because value types can be stored as values, not links, so boxing is not needed. Take ArrayList vs List<int> . If you want to put 1 in an ArrayList , you must set the CLR in the int field so that it can be stored in object[] . List<T> however uses T[] to store the contents of the list, so List uses int[] , which means that 1 does not need to be squared to put it in an array.

0
source
  • Boxing should be executed whenever you want to hold an int in an object variable.
  • The generic set int contains int[] instead of object[] .
  • Put int in object[] for a non-shared collection so that you enter an int field.
    Putting int in int[] behind a shared collection does not require any boxing.
+5
source

First, the stack and heap are implementation details. the type of value is not determined while on the stack. there is nothing to say that the concept of stack and heap will be used for all systems capable of hosting the CLR: http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types. aspx

Aside:

when the value type is marked in the box, the data in this value type is read, an object is created and the data is copied to the new object. if you box all the items in the collection, this is an overhead.

if you have a set of value types and iterate over them, this will happen for every read, then the elements will be unpacked (the back of the process) for reading the value only!

Shared collections are strongly typed for the type that is stored in them, and therefore do not need to do boxing or unpacking.

+3
source

Here is the answer around the unboxing / boxing part.

I'm not sure how this is implemented in mono, but common interfaces will help because the compiler creates a new function of a certain type, a different type is used for each (internally, there are several cases where it can use the same generated function). If functions of a particular type are generated, there is no need for a box / unbox type.

This is why the Collections.Generic library was a big hit in .NET 2.0 because collections were no longer required by boxing and became significantly more efficient.

As to why generics are better than other collections outside the boxing / unboxing field, it is that they also cause type. You can no longer easily drop a collection around which any type can be. It can prevent compilation errors, rather than seeing them at runtime.

+2
source

MSDN has a good article: Boxing and Unboxing (C # Programming Guide)

For simple assignments, boxing and unpacking are costly calculation processes. When a value type is placed in a box, a new object must be selected and constructed. To a lesser extent, the throw required for unpacking is also expensive.

Boxing is used to store value types in the garbage collected heap. A box is an implicit conversion of a value type into an object of type or any type of interface implemented by this type of value. Box value type allocates an instance of the object on the heap and copies the value to the new object.

Unboxing is an explicit conversion from a type object to a value type or from an interface type to a value type that implements the interface. The unboxing operation consists of:

  • Checking the instance of the object to make sure that this value is in the box of the given type.

  • Copy a value from an instance to a value type variable.

Also check: Learning Boxing in C #

And read the basics of Jeffrey Richter. Here are Two example chapters plus the full TOC from Jeffrey Richter "CLR via C #" (Microsoft Press, 2010) , which he published some time ago.

Also some notes by Jeffrey Richter read the CLR through C #:

It can be converted from a value type to a reference type using a mechanism called boxing.

Inside, what happens when an instance of a value type is placed in a box:

  • Memory is allocated from the managed heap. The amount of allocated memory is equal to the size required for the value type fields, plus two additional members of the service information (object pointer type and synchronization block index) required by all objects on the managed heap.

  • Type value fields are copied to the newly allocated heap memory.

  • The address of the object is returned. This address is now an object reference; the value type is now a reference type. The C # compiler automatically generates the IL code needed to enter an instance of the value type, but you still need to understand what is going on inside so you know about the code size and performance issues.


Note. It should be noted that FCL now includes a new set of common collection classes that make non-zero collection classes obsolete. For example, you should use the System.Collections.Generic.List class instead of the System.Collections.ArrayList class. Generic collection classes offer many improvements over nonequivalent equivalents. For example, the API has been refined and improved, and the performance of collection classes has also improved significantly. But one of the biggest improvements is that general collection classes allow you to work with sets of value types without requiring the items in the collection to be in a box / unpacked. This in itself greatly improves performance because fewer objects are created in the managed heap, which reduces the number of garbage collections your application requires. In addition, you will get compilation type security and your source code will be cleaner due to fewer throws. All of this will be explained in more detail in Chapter 12, “Generalization.”


I do not need a complete chapter. Read his book and you will receive detailed information about the process and receive answers. And BTW, the answer to your question is pretty much here on SO, around the Web and in many books. This is fundamental knowledge that you certainly must understand.

+2
source

Here's an interesting read from Eric Lippert (truth about value types): http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

regarding your statement:

The box pushes the value type (stack object) into the System.Object object and saves it on the Unbox heap, which unpacks this object on the heap holding this value type and throws it back onto the stack so that it can be used.

+1
source

Simply put, boxing and unboxing are time consuming. Why - it’s faster to run a known type from the very beginning, and then use this descriptor to execute.

  • When combining objects, various elements may be contained: string, int, double, etc., and you should check every time your operation with a variable matters.
  • Converting from one type to enother takes time.
  • Generic is much faster and encourages you to use them, there are old collections for backward compatibility.
0
source

Suppose I want to store a bunch of variables of type Long in a list, but the system did not support either generics of type values ​​or boxing. A way to store these values ​​would be to define a new BoxedLong class that contained one Long Value field. Then, to add a value to the list, you can create a new BoxedLong instance, set its Value field to the desired value and save it in the list. To get the value from the list, one could get the BoxedLong object from the list and take the value from its Value field.

When a value type is passed to an object waiting for an object, this essentially happens under the hood, with the exception of no new identifier names.

When using generics with value types, the system does not use a value holder class and passes it to routines that expect to work with objects. Instead, the system creates a new version of the routine that will work with the value of the type in question. If five different types of values ​​are passed to the general routine, five different versions of this procedure will be created. In general, this will give more code than using the class of the owner of the value, but the code will have to do less work each time the value is transferred or retrieved. Since most routines will have many values ​​of each type, transmitted or exited, the cost of generating different versions of the routine will more than pay off by eliminating boxing / unpacking operations.

0
source

All Articles