Introduction.
Boxing and unboxing is a
essential concept in VB.NET's type system. With Boxing
and unboxing one can link between value-types and
reference-types by allowing any value of a value-type to
be converted to and from type object. Boxing and
unboxing enables a unified view of the type system
wherein a value of any type can ultimately be treated as
an object. Converting a value type to reference type is
called Boxing.Unboxing is an explicit operation.
VB.NET provides a "unified type
system". All types-including value types-derive from the
type object. It is possible to call object methods on
any value, even values of "primitive" types such as int.
The example
Imports System
Class Test
Shared
Sub Main()
Console.WriteLine(3.ToString())
End
Sub
'Main
End
Class
'Test
calls the object-defined
ToString method on an integer literal.
The example
Class Test
Shared
Sub Main()
Dim i
As
Integer = 1
Dim o
As
Object = i
' boxing
Dim j
As
Integer =
CInt(o)
' unboxing
End
Sub
'Main
End
Class
'Test
An int value can be converted
to object and back again to int.
This example shows both boxing
and unboxing. When a variable of a value type needs to
be converted to a reference type, an object box is
allocated to hold the value, and the value is copied
into the box.
Unboxing is just the opposite.
When an object box is cast back to its original value
type, the value is copied out of the box and into the
appropriate storage location.
Boxing conversions.
A boxing conversion permits any
value-type to be implicitly converted to the type object
or to any interface-type implemented by the value-type.
Boxing a value of a value-type consists of allocating an
object instance and copying the value-type value into
that instance.
For example any value-type G,
the boxing class would be declared as follows:
Class vBox
Private value
As G
Sub
New(ByVal
g As G)
value = g
End
Sub
'New
End
Class
BoxBoxing of a value v of type
G now consists of executing the expression new G_Box(v),
and returning the resulting instance as a value of type
object.
Thus, the statements
Dim i
As
Integer = 12
Dim box
As
Object = i
conceptually correspond to
Dim i
As
Integer = 12
Dim box =
New int_Box(i)
Boxing classes like G_Box and int_Box above don't
actually exist and the dynamic type of a boxed value
isn't actually a class type. Instead, a boxed value of
type G has the dynamic type G, and a dynamic type check
using the is operator can simply reference type G. For
example,
Dim i
As
Integer = 12
Dim box
As
Object = i
If
TypeOf box
Is
Integer
Then
Console.Write("Box contains an int")
End
If
will output the string "Box contains an integer" on the
console.
A boxing conversion implies
making a copy of the value being boxed. This is
different from a conversion of a reference-type to type
object, in which the value continues to reference the
same instance and simply is regarded as the less derived
type object.
For example, given the
declaration.
Structure
Point
Public x, y
As
Integer
Public Sub
New(ByVal
x As
Integer,
ByVal y
As
Integer)
Me.x = x
Me.y = y
End
Sub
'New
End
Structure
'Point
the following statements
Dim
p As
New Point(10, 10)
Dim box
As
Object = p
p.x = 20
Console.Write(CType(box,
Point).x)
will output the value 10 on the
console because the implicit boxing operation that
occurs in the assignment of p to box causes the value of
p to be copied. Had Point instead been declared a class,
the value 20 would be output because p and box would
reference the same instance.
Unboxing conversions.
An unboxing conversion permits an explicit conversion
from type object to any value-type or from any
interface-type to any value-type that implements the
interface-type. An unboxing operation consists of first
checking that the object instance is a boxed value of
the given value-type, and then copying the value out of
the instance.
Unboxing conversion of an object box to a value-type G
consists of executing the expression ((G_Box)box).value.
Thus, the statements
Dim box
As
Object = 12
Dim i
As
Integer =
CInt(box)
conceptually correspond to
Dim box =
New int_Box(12)
Dim i
As
Integer =
CType(box,
int_Box).value.
For an unboxing conversion to a given value-type to
succeed at run-time, the value of the source argument
must be a reference to an object that was previously
created by boxing a value of that value-type. If the
source argument is null or a reference to an
incompatible object, an InvalidCastException is thrown.
Conclusion.
This type system unification
provides value types with the benefits of object-ness
without introducing unnecessary overhead. For programs
that don't need int values to act like objects, int
values are simply 32-bit values. For programs that need
int values to behave like objects, this capability is
available on demand. This ability to treat value types
as objects bridges the gap between value types and
reference types that exists in most languages.