tags:

views:

1269

answers:

5

Is there any difference between the two statements:

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

I have seen many samples that use PInvoke that prefer the first syntax if the myPtr argument is sent by ref to the called function. If I'll replace all new IntPtr(0) with IntPtr.Zero in my application, will it cause any damage?

+4  A: 

They are functionally equivalent, so it should cause no problems.

IntPtr.Zero represents the default state of the structure (it is declared but no constructor is used), so the default value of the intptr (void*) would be null. However, as (void*)null and (void*)0 are equivalent, IntPtr.Zero == new IntPtr(0)

Edit: While they are equivalent, I do recommend using IntPtr.Zero for comparisons since it simply is easier to read.

Richard Szalay
That's what I think too... :)So why there are about a million samples on the web that use the new IntPtr(0)? Isn't it better to use the static variable version?
Yuval Peled
A: 

It's mostly a matter encapsulation (and of performance, but to a much lesser extent). At some moment in the future Microsoft may decide (though it's very unlikely) that an unitialized pointer value will from now on equal to 0xDEADBEEF, thus rendering all new IntPtr(0) code invalid.

As far as performance is concerned, MSDN says this:

For example, assume the variable, ip, is an instance of IntPtr. You can determine if it has been set by comparing it to the value returned by a constructor, for example: " if ip != new IntPtr(0)... ". However, invoking a constructor to get an unintialized pointer is inefficient. It is better to code either " if ip != IntPtr.Zero... ", or " if !IntPtr.Zero.Equals(ip)... ".

Anton Gogolev
-1: The first paragraph is not correct. new IntPtr(0) does not create an uninitialized IntPtr; it creates one that is explicitly initialized to zero. As does IntPtr.Zero. The two are absolutely semantically identical.
Greg Beech
The point is that IntPtr.Zero can potentially be changed to be equal to something other than zero without breaking any third-party code.
Anton Gogolev
No, it can't. It is an IntPtr with a value of zero, as the name indicates. From MSDN: "A read-only field that represents a pointer or handle that has been initialized to zero." (http://msdn.microsoft.com/en-us/library/system.intptr.zero.aspx)
Greg Beech
+3  A: 

The use of IntPtr.Zero will allow you to avoid a new instance of IntPtr.

from msdn:

Use this field to efficiently determine whether an instance of IntPtr has been set to a value other than zero

bruno conde
true, but in that does not apply to either of the cases the OP mentions.
Andrew Grant
+1  A: 

What happens if you pass IntPtr.Zero by ref, and the recipient tries to modify the reference? From that moment forth, would IntPtr.Zero != new IntPtr(0), or would the recipient receive some kind of exception upon trying to make the change?

I'm not sure about this, but it seems like a reasonable explanation.

Drew Noakes
You cannot pass a readonly field as a ref parameter.
Richard Szalay
That's what I was afraid of... But I think that it doesn't happen. Because I'm not really sending IntPtr.Zero by ref. I'm probably sending a boxing of the myPtr. But I'm not really sure about it either... Hence my question... :)
Yuval Peled
If you assign IntPtr.Zero to a variable before passing it to your other method, you are not passing IntPtr.Zero but a local copy (it's a struct).
Richard Szalay
+4  A: 

IntPtr is a value type, so unlike String.Empty there's relatively little benefit in having the static property IntPtr.Zero

As soon as you pass IntPtr.Zero anywhere you'll get a copy, so for variable initialisation it makes no difference:

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

There is one exception, and that's comparison:

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

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

As a couple of posters have already said.

Keith