chenedor said:
Hi all
I am a bit confuse about unboxing... what is the difference and what
is best practice ?
object o = __box(1234);
int n = *dynamic_cast<__box int*>(o);
A couple of comments. First, the above may exhibit undefined behavior or
cause a NullReferenceException. If the dynamic_cast fails, it returns a
null pointer, which the code above de-references anyway. If you're going to
use dynamic_cast, it only makes sense if you write something like:
__box int* pi = dynamic_cast<__box int*>(o);
if (pi)
n = *pi;
Second, under the CLR all casts are dynamic as is the un-boxing operation.
Here's a simple example to illustrate the differences under the covers:
#using <mscorlib.dll>
#pragma managed
void f()
{
System::Object* o = __box(1234);
int n = *dynamic_cast<__box int*>(o);
int m = *static_cast<__box int*>(o);
}
Compile this with cl -clr -c -FAsc and look at the .COD file that's
produced:
; 6 : {
0000c 14 ldnull 0 ; i32 0x0
0000d 0a stloc.0 ; _o$
; 7 : System::Object* o = __box(1234);
0000e 20 d2 04 00 00 ldc.i4 1234 ; i32 0x4d2
00013 8c 00 00 00 00 box ?<clref>@Int32@System@@2HA
00018 0a stloc.0 ; _o$
; 8 :
; 9 : int n = *dynamic_cast<__box int*>(o);
00019 06 ldloc.0 ; _o$
0001a 75 00 00 00 00 isInst ?<clref>@Int32@System@@2HA
0001f 79 00 00 00 00 unbox ?<clref>@Int32@System@@2HA
00024 4a ldind.i4
00025 0c stloc.2 ; _n$
; 10 :
; 11 : int m = *static_cast<__box int*>(o);
00026 06 ldloc.0 ; _o$
00027 79 00 00 00 00 unbox ?<clref>@Int32@System@@2HA
0002c 4a ldind.i4
0002d 0b stloc.1 ; _m$
$L1344:
; 12 : }
Note that the unbox operation is identical in both cases, and that both
cases pass the expected type (System::Int32) to the unbox operation. The
only difference is that dynamic_cast inserted an isInst instruction, the
result of which was ignored.
So, there is reason to use dynamic_cast if you're not sure the cast will
succeed, but in those cases be sure to test the result of the cast before
using it, otherwise you're just turning a bad cast exception into a numm
reference exception. When you "know" that the cast will succeed, use
static_cast. The same rules apply in native C++ programming, except that
de-referencing a null pointer is undefined behavior instead of a guaranteed
NullReferenceException.
-cd