Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将IntPtr强制转换为int有时仅起作用_C#_.net_Casting_Intptr - Fatal编程技术网

C# 将IntPtr强制转换为int有时仅起作用

C# 将IntPtr强制转换为int有时仅起作用,c#,.net,casting,intptr,C#,.net,Casting,Intptr,考虑以下代码: IntPtr p = (IntPtr) (long.MaxValue); // Not a valid ptr in 32 bit, // but this is to demonstrate the exception for 64 bit Console.WriteLine((int)(long)p); Console.WriteLine((int)p); 第二条WriteLine在64位上编译和运

考虑以下代码:

IntPtr p = (IntPtr) (long.MaxValue); // Not a valid ptr in 32 bit, 
                                     // but this is to demonstrate the exception for 64 bit
Console.WriteLine((int)(long)p);
Console.WriteLine((int)p);
第二条
WriteLine
在64位上编译和运行时抛出
OverflowException
。这是有案可查的

我的问题是:为什么

将指针转换为
Int32
时,概念上会丢失所有指针语义,并在语义上将指针简化为其整数表示形式。那么为什么要抛出一个异常,而不是截断该值以适应整数呢?那将是最明智的做法。因为如果程序员真的想不惜一切代价避免截断,为什么首先要把它放在int中呢

这种设计是故意的,还是转换运算符的实现不完整


我觉得在阅读了第一段评论之后,有必要进行一些澄清。我的问题也可以理解为:

是否有一个实际的用例,您可以将
IntPtr
转换成
int
,然后再将其转换回
IntPtr
,这样之后它仍然有效



作为对询问用例的人的答复,让我给出将
IntPtr
放入
int
的唯一用例,我可以想出:为非托管对象周围的托管包装器对象实现
GetHashCode
IntPtr
int
的强制转换操作符的实现如下(从)

如您所见,对于Windows x64,它将显式使用
checked
强制溢出异常。(我很高兴它做到了!)

相反,当您先将其转换为
long
,然后自己转换为
int
时,默认情况下,它将被取消选中
,因此不会引发异常


我只能猜测他们这样做的原因,但似乎很明显,截断指针几乎总是一件坏事,因此他们决定,如果发生截断,代码应该抛出异常。
IntPtr
to
int
的cast操作符的实现如下(从)

如您所见,对于Windows x64,它将显式使用
checked
强制溢出异常。(我很高兴它做到了!)

相反,当您先将其转换为
long
,然后自己转换为
int
时,默认情况下,它将被取消选中
,因此不会引发异常


我只能猜测他们这样做的原因,但似乎很明显,截断指针几乎总是一件坏事,因此他们决定,如果发生截断,代码应该抛出一个异常。

截断指针有什么意义?如果你真的想这样做,你总是可以明确地这样做。你应该庆幸的是,默认情况是检测到这种情况并抛出异常,不管你认为从哲学的角度来看什么是最具美学吸引力的。请注意,转换指针最常见的原因不是在某种真空中欣赏它的位——这是因为最终值会被转换回来,可能是在操作之后。当价值被冲掉的时候,祝你好运。你正试图把一头64磅的猪塞进一只32磅的叉子里。当然,它溢了出来。长距离投射仅仅帮助猪在没有尖叫声的情况下减少了32磅体重,如果表达式
未选中
,则截断是无声的。默认情况下,没有足够的程序员更改btw的项目设置。这种溢出尤其常见,因为Windows 8.1支持将内存分配到4 GB以上。请注意,如果在启用溢出检查的情况下编译,则即使对于常规整数,使用强制转换将64位值截断为32位也会失败。截断并不是“在所有情况下”都应该起作用的东西。它总是可以通过显式屏蔽位来工作的。显式是一件好事,但尤其是当您丢弃指针的位时。在.Net 4之前的.Net版本中,除了通过
int
之外,您不能执行指针算术是不正确的。您可以始终将
long
IntPtr
一起使用,并且您始终能够在
不安全的
代码中使用实际指针。@MatthewWatson:重点是,对于32位代码,通过转换为
int
来进行指针运算至少是合理的。(有一些不相关的原因可以避免
不安全的
代码,比如需要更高的信任度。)当然,谨慎的开发人员不会仅仅因为知道他们的代码现在是32位类型就使用32位类型,但开发人员并不谨慎。而且还痴迷于性能。特别是那些围绕指针进行的转换。截断指针是如何明智的呢?如果你真的想这样做,你总是可以明确地这样做。你应该庆幸的是,默认情况是检测到这种情况并抛出异常,不管你认为从哲学的角度来看什么是最具美学吸引力的。请注意,转换指针最常见的原因不是在某种真空中欣赏它的位——这是因为最终值会被转换回来,可能是在操作之后。当价值被冲掉的时候,祝你好运。你正试图把一头64磅的猪塞进一只32磅的叉子里。当然,它溢了出来。长距离投射仅仅帮助猪在没有尖叫声的情况下减少了32磅体重,如果表达式
未选中
,则截断是无声的。默认情况下,没有足够的程序员更改btw的项目设置。这种溢出尤其常见,因为Windows 8.1支持将内存分配到4 GB以上。请注意,如果在启用溢出检查的情况下编译,则即使对于常规整数,使用强制转换将64位值截断为32位也会失败。截断并不是“在所有情况下”都应该起作用的东西。它总是可以通过显式屏蔽位来工作的。直言不讳是一个很好的方法
    [System.Security.SecuritySafeCritical]  // auto-generated
    [System.Runtime.Versioning.NonVersionable]
    public unsafe static explicit operator int (IntPtr  value) 
    {
        #if WIN32
            return (int)value.m_value;
        #else
            long l = (long)value.m_value;
            return checked((int)l);
        #endif
    }