Each non-string object that does not contain a string stored in the heap contains an 8- or 16-byte header (sizes for 32/64-bit systems), and then the contents of this public and private fields of this object. In the arrays and rows, the header is indicated above, as well as several bytes that determine the length of the array and the size of each element (and, possibly, the number of dimensions, the length of each additional dimension, etc.), followed by all fields of the first element, then all fields second, etc. Given a reference to an object, the system can easily examine the header and determine what type it has.
A reference type storage location contains a four- or eight-byte value that uniquely identifies an object stored in the heap. In existing implementations, this value is a pointer, but it's easier (and semantically equivalent) to think of it as an "object identifier".
Value type storages store the contents of value type fields, but they do not have an associated header. If the code declares a variable of type Int32 , there is no need to store information with that Int32 saying what it is. The fact that this location contains Int32 is effectively stored as part of the program, and therefore it does not need to be stored in the place itself. This represents a big savings if, for example, one has a million objects, each of which has an Int32 field. Each of the objects that have Int32 has a header that identifies the class that can use it. Since one copy of this class of code can work on any of millions of instances, the fact that the field is an Int32 part of the code is much more efficient than storing for each of these fields contains information about what it is.
Boxing is necessary when a request is made to transfer the contents of a data type data store to a code that does not know to expect this particular type of value. Code that expects objects of an unknown type can accept a reference to an object stored on the heap. Since each object stored on the heap has a header that determines what type of object it is, the code can use this header whenever it is necessary to use the object in a way that requires knowing its type.
Note that in .net you can declare what are called generic classes and methods. Each such declaration automatically generates a family of classes or methods that are identical, except for the type of object they expect to act on. If you pass Int32 to the DoSomething<T>(T param) routine, this will automatically generate a version of the routine in which each instance of type T will be effectively replaced with Int32 . This version of the procedure will know that each storage location declared as type T contains Int32 , therefore, as in the case when the procedure was hard-coded to use the Int32 storage location, it will not be needed to store information about the type with these locations.
supercat Jun 09 2018-12-12T00: 00Z
source share