経緯
Windows APIを使ってるときに、タイトルの現象に遭遇したので原因を探ってみた。
実験用コード
using System;
class CastTest
{
[STAThread]
static void Main(string[] args)
{
IntPtr t1 = new IntPtr(0x7FFFFFFFu);
IntPtr t2 = new IntPtr(0x80000000u);
try{
uint tmp = 0x80000000u;
Console.WriteLine(tmp);
uint t1Cast = (uint)t1;
Console.WriteLine(t1Cast);
uint t2Cast = (uint)t2; // ここで例外が発生する
Console.WriteLine(t2Cast);
}
catch(OverflowException e){
Console.WriteLine(e);
}
}
}
実行結果
2147483648
2147483647
System.OverflowException: 算術演算の結果オーバーフローが発生しました。
場所 CastTest.Main(String[] args)
原因 - 内部的にはintにキャストしている
ildasmで uint t2Cast = (uint)t2;
に該当する処理のコンパイル後コードを確認したところ、下記となっている。
intにキャストしてらっしゃる。。
call int32 [mscorlib]System.IntPtr::op_Explicit(native int)
ILSpyで上記のメソッドをみると、下記となっている。ご丁寧にもchecked
が付いている。ので、オーバーフロー例外を投げる。
public unsafe static explicit operator int(IntPtr value)
{
long num = (long)value.m_value;
return checked((int)num);
}
回避方法(暫定)
とりあえずlong型へのキャストを経由する。
(checkedの有効な中から呼ばれた場合、63bit目が立ってると多分同じ目に遭う…)
ちなみに ILSpyでlongにキャストしているメソッドらしきものをみると、
public unsafe static explicit operator long(IntPtr value)
{
return (long)value.m_value;
}
となっている。