これは少し奇妙に思えることに同意するので、いくつかのテストを実行しました。
テスト #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 はスタックに置かれ、 に変換されますint64
が、 unsigned から signed への追加の変換はありません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)
オーバーフローの場合に必要な unsigned から signed へのキャストがあります。
残念ながら、これは元の質問には答えません。
更新:回答の間違った部分を削除したため、実際の回答は残りません。ただし、役立つと思うので、回答全体を削除していません。