JavaScript EditorDhtml editor     Free javascript download 

Main Page

The usage of a tracking handle to reference a value type has changed from Managed Extensions for C++ to Visual C++ 2005.

Boxing is a peculiarity of the CLR unified type system. Value types directly contain their state, while reference types are an implicit duple: the named entity is a handle to an unnamed object allocated on the managed heap. Any initialization or assignment of a value type to an Object, for example, requires that the value type be placed within the CLR heap – this is where the image of boxing it arises – first by allocating the associated memory, then by copying the value type’s state, and then returning the address of this anonymous Value/Reference hybrid. Thus, when one writes in C#

В CopyCode imageCopy Code
object o = 1024; // C# implicit boxing

there is a great deal more going on than is made apparent by the simplicity of the code. The design of C# hides the complexity not only of what operations are taking place under the hood, but also of the abstraction of boxing itself. Managed Extensions for C++, on the other hand, concerned that this would lead to a false sense of efficiency, puts it in the user’s face by requiring an explicit instruction:

В CopyCode imageCopy Code
Object *o = __box( 1024 ); // Managed Extensions explicit boxing

as if in this case one had any choice. In my opinion, forcing the user to make an explicit request in these cases is at best the equivalent of one’s mother repeatedly demanding as one is trying to leave the house, "Now you will be careful, won’t you?" On the one hand, at some point, one has to internalize the admonition; that's called maturation. On the other hand, at some point, one has to trust in the maturation of one's children. Substitute the language designer for one's mother, and the programmer for one's child, and that is why boxing is implicit under Visual C++ 2005:

В CopyCode imageCopy Code
Object ^o = 1024; // new syntax implicit boxing

The __box keyword serves a second more vital service within Managed Extensions, one that is absent by design from languages such as C# and Visual Basic: it provides both a vocabulary and tracking handle for directly manipulating a boxed instance on the managed heap. For example, consider the following small program:

В CopyCode imageCopy Code
int main() {
   double result = 3.14159;
   __box double * br = __box( result );

   result = 2.7; 
   *br = 2.17;   
   Object * o = br;

   Console::WriteLine( S"result :: {0}", result.ToString() ) ;
   Console::WriteLine( S"result :: {0}", __box(result) ) ;
   Console::WriteLine( S"result :: {0}", br );

The underlying code generated for the three invocations of WriteLine show the various costs of accessing the value of a boxed value type (thanks to Yves Dolce for pointing out these differences), where the indicated lines show the overhead associated with each invocation.

В CopyCode imageCopy Code
// Console::WriteLine( S"result :: {0}", result.ToString() ) ;
ldstr      "result :: {0}"
ldloca.s   result  // ToString overhead
call       instance stringВ  [mscorlib]System.Double::ToString()  // ToString overhead
call       void [mscorlib]System.Console::WriteLine(string, object)

// Console::WriteLine( S"result :: {0}", __box(result) ) ;
Ldstr    " result :: {0}"
box    [mscorlib]System.Double // box overhead
call    void [mscorlib]System.Console::WriteLine(string, object)

// Console::WriteLine( S"result :: {0}", br );
ldstr    "result :: {0}"
call     void [mscorlib]System.Console::WriteLine(string, object)

Passing the boxed value type directly to Console::WriteLine eliminates both the boxing and the need to invoke ToString(). (Of course, there is the earlier boxing to initialize br, so of course we don’t really gain anything unless we really put br to work.

In the new syntax, the support for boxed value types is considerably more elegant and integrated within the type system while retaining its power. For example, here is the translation of the earlier small program:

В CopyCode imageCopy Code
int main()
   double result = 3.14159;
   double^ br = result;
   result = 2.7;
   *br = 2.17;
   Object^ o = br;
   Console::WriteLine( "result :: {0}", result.ToString() );
   Console::WriteLine( "result :: {0}", result );
   Console::WriteLine( "result :: {0}", br );

See Also


How to: Explicitly Request Boxing


Value Types and Their Behaviors

JavaScript EditorDhtml editor     Free javascript download