int vs IntPtr when you have a handle?
First a background question:
In general, what is the difference between int
and IntPtr
? My guess is that it is an actual object rather than a value like an int
or byte
is. Assuming that is true:
So they are not the same. Yet I see handles represented as both.
- IntPtr:
Control.Handle
int (or uint): A PInvoke can be setup to return an
int
and it works just fine:[DllImport("coredll.dll", SetLastError = true)] public static extern int GetForegroundWindow(); private string GetActiveWindow() { const int nChars = 256; int handle = 0; StringBuilder Buff = new StringBuilder(nChars); handle = CoreDLL.GetForegroundWindow(); if (Core开发者_JAVA技巧DLL.GetWindowText(handle, Buff, nChars) > 0) { return Buff.ToString(); } return ""; }
So, int
vs IntPtr
? Does it matter for handles? Can you use either?
int
is 32 bits long. IntPtr
is as long as a pointer for your architecture. Therefore, a pointer can be stored into an int
only on 32 bit systems, while it can always be stored in an IntPtr
.
Notice that your "int as a return value" example does not use an int
to hold a pointer, but just to hold a numeric value. This does not mean that an int
is automatically the correct size though: the author of that P/Invoke signature should have gone to the documentation for GetForegroundWindow
and see that it returns a HWND
.
Then, from windef.h
in the Platform SDK (or this MSDN page) we can see that a HWND
is a HANDLE
which is a PVOID
which is... a pointer!
Therefore, as far as I can tell, that signature is wrong, as the size of the return value of GetForegroundWindow
depends on the architecture. Thus, it should also be an IntPtr
.
Update:
While it can be inferred from the above, I think it's worthwhile to explicitly point out that:
- Erroneously using
int
instead ofIntPtr
in 32-bit applications will never cause a problem, even if they run on 64-bit Windows; since most applications are 32-bit at this point in time, this will let you get away such mistakes very often. - Erroneously using
int
instead ofIntPtr
in 64-bit applications is not guaranteed to cause problems, since it is quite possible that in practice the values being encountered will fit in the 32 bits of theint
. This further lessens the probability that a mistake will manifest as an application error.
Therefore, for an error to actually manifest there are three conditions that have to be satisfied at the same time:
- An
int
is used where anIntPtr
should be. - The executable image is 64-bit.
- A value returned by some PInvoke call and stored as an
int
is actually larger than 32 bits.
精彩评论