I agree that this seemed a little strange, so I did some tests.
Test No. 1: Make a listing of oolong and long
ulong ul = UInt64.MaxValue; long l = Int64.MaxValue; IntPtr ulptr = (IntPtr)ul; IntPtr lptr = (IntPtr)l;
Since cast IntPtr states that it can throw an OverflowException , I expected that casting (IntPtr)ul would throw an exception. This is not true. Imagine my surprise when a throw (IntPtr)l threw an OverflowException . Having looked at this, I saw that my project was configured to compile for x86 , so now it became clear that this exception is Int64.MaxValue too large to fit into 32-bit IntPtr .
Test # 2: place the checked block around the same code.
Now I really expected that casting (IntPtr)ul would throw an exception, and that happened.
It made me think about what happened to the first actor. Using ildasm for untested code leads to the following:
IL_0000: nop IL_0001: ldc.i4.m1 IL_0002: conv.i8 IL_0003: stloc.0 IL_0004: ldc.i8 0x7fffffffffffffff IL_000d: stloc.1 IL_000e: ldloc.0 IL_000f: call native int [mscorlib]System.IntPtr::op_Explicit(int64) IL_0014: stloc.2 IL_0015: ldloc.1 IL_0016: call native int [mscorlib]System.IntPtr::op_Explicit(int64)
So, -1 is int64 stack and converted to int64 , but there is no extra conversion from unsigned to signed int64 .
The checked version is slightly different:
IL_0000: nop IL_0001: nop IL_0002: ldc.i4.m1 IL_0003: conv.i8 IL_0004: stloc.0 IL_0005: ldc.i8 0x7fffffffffffffff IL_000e: stloc.1 IL_000f: ldloc.0 IL_0010: conv.ovf.i8.un IL_0011: call native int [mscorlib]System.IntPtr::op_Explicit(int64) IL_0016: stloc.2 IL_0017: ldloc.1 IL_0018: call native int [mscorlib]System.IntPtr::op_Explicit(int64)
Now there is a cast from unsigned to signed, which is necessary in case of overflow.
Unfortunately, this does not answer the original question.
Update: I deleted the part of the answer that was incorrect and did not leave any real answer. However, I expect this to be useful, so I have not deleted the whole answer.
Joel rondeau
source share