我同意这看起来有点奇怪,所以我进行了几次测试。
测试#1:做一个 ulong 和一个 long 的演员表
ulong ul = UInt64.MaxValue;
long l = Int64.MaxValue;
IntPtr ulptr = (IntPtr)ul;
IntPtr lptr = (IntPtr)l;
因为IntPtr
演员表声明它可能会抛出一个OverflowException
,所以我期待 (IntPtr)ul
演员表抛出一个异常。它没。想象一下,当(IntPtr)l
演员抛出一个OverflowException
. 调查这个,我看到我的项目被设置为编译x86
,所以现在这个异常是有意义的——Int64.MaxValue
太大而不能适应 32 位的IntPtr
.
测试#2:checked
在相同的代码周围放置一个块。
现在,我真的希望(IntPtr)ul
演员会抛出异常,而且确实如此。
这让我想知道第一个演员发生了什么。在未经检查的代码上使用ildasm
会导致以下结果:
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)
所以 -1 被放入堆栈并转换为 an int64
,但没有从 unsigned 到有符号的额外转换int64
。
checked
版本略有不同:
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)
现在有一个从无符号到有符号的转换,这在溢出的情况下是必要的。
不幸的是,这并不能回答最初的问题。
更新:我删除了答案中不正确的部分,因此没有留下任何实际答案。但是,我希望它会有所帮助,因此我没有删除整个答案。