C# 新IntPtr(0)与IntPtr.0

C# 新IntPtr(0)与IntPtr.0,c#,.net,pinvoke,C#,.net,Pinvoke,这两种说法有什么区别吗 IntPtr myPtr = new IntPtr(0); IntPtr myPtr2 = IntPtr.Zero; 我见过许多使用PInvoke的示例,如果myPtr参数是通过ref发送给被调用函数的,那么它们更喜欢第一种语法。 如果在我的应用程序中用IntPtr.Zero替换所有新的IntPtr(0),它会造成任何损坏吗?它们在功能上是等效的,因此应该不会引起任何问题 IntPtr.Zero表示结构的默认状态(已声明但未使用构造函数),因此IntPtr(void*)

这两种说法有什么区别吗

IntPtr myPtr = new IntPtr(0);
IntPtr myPtr2 = IntPtr.Zero;
我见过许多使用PInvoke的示例,如果myPtr参数是通过ref发送给被调用函数的,那么它们更喜欢第一种语法。
如果在我的应用程序中用IntPtr.Zero替换所有新的IntPtr(0),它会造成任何损坏吗?

它们在功能上是等效的,因此应该不会引起任何问题

IntPtr.Zero
表示结构的默认状态(已声明但未使用构造函数),因此
IntPtr(void*)
的默认值应为
null
。但是,由于
(void*)null
(void*)0
是等效的,
IntPtr.Zero==新的IntPtr(0)


编辑:虽然它们是等效的,但我建议使用
IntPtr.Zero
进行比较,因为它更易于阅读。

这主要是一个封装问题(和性能问题,但程度要小得多)。在将来的某个时刻,微软可能会决定(尽管可能性不大)从现在起,一个统一化的指针值将等于
0xDEADBEEF
,从而使所有
新的IntPtr(0)
代码无效

就性能而言,MSDN表示:

例如,假设变量
ip
,是
IntPtr
的一个实例。您可以通过将它与构造函数返回的值进行比较来确定它是否已被设置,例如:“if ip!=new IntPtr(0)…”。然而,调用构造函数来获取未初始化的指针效率很低。最好编写“
如果ip!=IntPtr.Zero…
”,或“
如果!IntPtr.Zero.Equals(ip)…


使用
IntPtr.Zero
可以避免出现
IntPtr
的新实例

发件人:

使用此字段可以有效地 确定 IntPtr已设置为其他值 大于零


如果您通过ref传递
IntPtr.Zero
,并且收件人尝试修改引用,会发生什么情况?从那一刻起,
IntPtr.Zero!=新建IntPtr(0)
,或者收件人在尝试进行更改时是否会收到某种异常


我不确定这一点,但这似乎是一个合理的解释。

IntPtr
是一种值类型,因此与
String.Empty不同。使用静态属性
IntPtr.Zero

只要你通过
IntPtr.Zero
任何地方,你都会得到一份副本,因此对于变量初始化来说,这没有什么区别:

IntPtr myPtr = new IntPtr(0);
IntPtr myPtr2 = IntPtr.Zero;

//using myPtr or myPtr2 makes no difference
//you can pass myPtr2 by ref, it's now a copy
有一个例外,那就是比较:

if( myPtr != new IntPtr(0) ) {
    //new pointer initialised to check
}

if( myPtr != IntPtr.Zero ) {
    //no new pointer needed
}

正如一些海报已经说过的。

抖动可以内联IntPtr.Zero,就像内联IntPtr.Size一样。

我也是这么想的…:)那么,为什么网上有大约一百万个样本使用新的IntPtr(0)?使用静态变量版本不是更好吗?-1:第一段不正确。新IntPtr(0)不会创建未初始化的IntPtr;它创建一个显式初始化为零的。IntPtr.Zero也是如此。这两者在语义上完全相同。关键是IntPtr.Zero可以在不破坏任何第三方代码的情况下被更改为等于零以外的值。不,它不能。正如名称所示,它是一个值为零的IntPtr。来自MSDN:“一个只读字段,表示已初始化为零的指针或句柄。”()他的意思是在新的.Net平台中,IntPtr.zero可以等于5,并且不会破坏任何代码。然而,这是错误的,因为它是一种值类型,如果他们更改它,它将破坏代码。当人们使用它进行检查时,编译器会硬编码值0。指针实际上是内存中的地址。不能使用固定值作为默认值;这些地址实际上可能被使用。而0点在内存寻址的最开始;一些不应该被高层访问的东西,因为它可能是引导机制的核心。这就是我害怕的。。。但我认为这不会发生。因为我不是真的通过ref发送IntPtr.Zero。我可能是发送了一盒myPtr。但我也不是很确定。。。因此我的问题……:)如果在将IntPtr.Zero传递给另一个方法之前将其分配给变量,则传递的不是IntPtr.Zero,而是一个本地副本(它是一个结构)。true,但这不适用于OP提到的任何一种情况。
IntPtr.Zero
更具可读性。我认为坚持下去会更好