The code snippets used in this module if any are Visual C++ .Net 2003 dominated and if compiled using Visual C++ .Net 2005 you need to use the /clr:oldSyntax option). The following are the topics available in this module.
Managed Extensions for C++: __box Keyword
This topic applies only to version 1 of Managed Extensions for C++. This syntax should only be used to maintain version 1 code. Use Implicit Boxing for the equivalent functionality in the new syntax. This keyword creates a managed copy of a __value class object. The syntax is:
The __box keyword is used to create a managed object (derived from System::ValueType) from an existing __value class object. When the __box keyword is applied to a __value class:
This process is known as boxing. This enables any __value class object to be used in generic routines that work for any managed object because the managed object indirectly inherits from System::Object since System::ValueType inherits from System::Object. The newly created boxed object is a copy of the __value class object. Therefore, modifications to the value of the boxed object do not affect the contents of the __value class object. The following is an example that does boxing and unboxing:
|
In the following example, an unmanaged value type (V) is boxed and passed as a managed parameter to the Positive function.
// Test.cpp : main project file.
// keyword, __box
// compile with: /clr:oldSyntax
#include "stdafx.h"
#using <mscorlib.dll>
using namespace System;
__value struct myV
{
int i;
};
// expects a managed class
void Positive(Object*) {}
int main()
{
// allocate and initialize
myV myv = {100};
Console::Write("myv.i = ");
Console::WriteLine(myv.i);
// copy to the common language runtime heap
__box myV* pBoxedV = __box(myv);
// treat as a managed class
Positive(pBoxedV);
// update the boxed version
pBoxedV->i = 200;
Console::Write("pBoxedV->i = ");
Console::WriteLine(pBoxedV->i);
return 0;
}
Output:
Implicit Boxing
The Visual C++ compiler now boxes value types to Object. This is possible because of a compiler-defined conversion to convert value types to Object. Boxing and unboxing enable value types to be treated as objects. Value types, including both struct types and built-in types such as int, can be converted to and from the type Object. The following sample shows how explicit boxing was done with Managed Extensions for C++.
// Test.cpp : main project file.
// explicit boxing
// compile with: /clr:oldSyntax
#include "stdafx.h"
#using <mscorlib.dll>
using namespace System;
__gc class A
{
public:
void func(System::Object * o){Console::WriteLine("In class A...");}
};
__value class V {};
__gc __interface IFace
{
void func();
};
__value class V1 : public IFace
{
public:
void func()
{ Console::WriteLine("In interface function..."); }
};
int main()
{
// example 1 explicit boxing
Int32 __box* bi = __box(100);
Console::Write("bi = ");
Console::WriteLine(bi);
// example 2 calling a member with explicit boxing
Int32 n = 200;
Console::WriteLine(S"n = {0}", __box(n)->ToString());
// example 3 explicit boxing for function calls
A * a = new A;
a->func(__box(n));
// example 4 explicit boxing for WriteLine function call
V v;
Console::WriteLine(S"Class {0} passed using implicit boxing", __box(v)->ToString());
// example 5 casting to a base with explicit boxing
V1 v1;
|
The following sample shows how implicit boxing works.
// Test.cpp : main project file.
// explicit boxing2 example
// compile with: /clr
#include "stdafx.h"
using namespace System;
ref class A
{
public:
void func(System::Object^ o){Console::WriteLine("In class A...");}
};
value class V {};
interface struct IFace
{
void func();
};
value class V1 : public IFace
{
public:
virtual void func()
{ Console::WriteLine("In funct, interface function..."); }
};
value struct V2
{
// conversion operator to System::Object
static operator System::Object^(V2 v2)
{
Console::WriteLine("Operator System::Object^...");
return (V2^)v2;
}
};
void func1(System::Object^){Console::WriteLine("In void func1(System::Object^)");}
void func1(V2^){Console::WriteLine("In func1(V2^)");}
void func2(System::ValueType^){Console::WriteLine("In func2(System::ValueType^)");}
void func2(System::Object^){Console::WriteLine("In func2(System::Object^)");}
int main()
{
// example 1 simple implicit boxing
Int32^ bi = 100;
Console::Write("bi = ");
Console::WriteLine(bi);
// example 2 calling a member with implicit boxing
Int32 n = 200;
Console::WriteLine("n = {0}", n.ToString());
// example 3 implicit boxing for function calls
A^ a = gcnew A;
a->func(n);
// example 4 implicit boxing for WriteLine function call
V v;
Console::WriteLine("Class {0} passed using implicit boxing", v);
// force boxing
Console::WriteLine("Class {0} passed with forced boxing", (V^)(v));
// example 5 casting to a base with implicit boxing
V1 v1;
IFace ^ iface = v1;
iface->func();
// example 6 user-defined conversion preferred over implicit boxing
// for function-call parameter matching
V2 v2;
// user defined conversion from V2 to System::Object preferred
// over implicit boxing will call void func1(System::Object^);
func1(v2);
// OK: Calls "static V2::operator System::Object^(V2 v2)"
func2(v2);
// Using explicit boxing: calls func2(System::ValueType^)
func2((V2^)v2);
return 0;
}
Output: