2010-11-30 20 views
12

Primero una pregunta de fondo:int vs IntPtr cuando tiene un controlador?

En general, ¿cuál es la diferencia entre int y IntPtr? Mi suposición es que es un objeto real en lugar de un valor como int o byte. Si se asume que es verdad:

lo que no son lo mismo. Sin embargo, veo mangos representados como ambos.

  1. IntPtr: Control.Handle
  2. int (o uint): Un PInvoke puede ser configurado para devolver un int y funciona muy bien:

    [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 (CoreDLL.GetWindowText(handle, Buff, nChars) > 0) 
        { 
         return Buff.ToString(); 
        } 
    
        return ""; 
    } 
    

Así, int vs IntPtr? ¿Importa para los mangos? ¿Puedes usar cualquiera?

Respuesta

27

int es de 32 bits de largo. IntPtr es tan largo como un puntero para su arquitectura. Por lo tanto, un puntero se puede almacenar en un int sólo en sistemas de 32 bits, mientras que puede siempre se almacena en un IntPtr.

cuenta de que su "int como valor de retorno" ejemplo hace no utilizar un int para contener un puntero, pero sólo para mantener un valor numérico. Esto no quiere decir que un int es automáticamente el tamaño correcto sin embargo: el autor de ese P/Invoke firma debería haber ido a la documentación de GetForegroundWindow y ver que devuelve un HWND.

Entonces, desde windef.h en el SDK de la plataforma (o this MSDN page) podemos ver que un HWND es una HANDLE que es un PVOID que es un puntero ...!

Por lo tanto, hasta donde puedo decir, esa firma es mal, ya que el tamaño del valor de retorno de GetForegroundWindow depende de la arquitectura. Por lo tanto, también debe ser un IntPtr.

Actualización:

Si bien se puede inferir de lo anterior, creo que vale la pena señalar explícitamente que:

  • Erróneamente usando int en lugar de IntPtr en aplicaciones de 32 bits nunca causa un problema, incluso si se ejecutan en Windows de 64 bits; ya que la mayoría de las aplicaciones son de 32 bits en este momento, esto le permitirá evitar estos errores muy a menudo.
  • Erróneamente usando int en lugar de IntPtr en aplicaciones de 64 bits es no garantizada para causar problemas, ya que es muy posible que en la práctica los valores que se encuentran quepa en los 32 bits de la int. Esto disminuye aún más la probabilidad de que un error se manifieste como un error de aplicación.

Por lo tanto, para un error al manifestar realmente hay tres condiciones que deben cumplirse al mismo tiempo:

  1. Un int se utiliza cuando un IntPtr debe ser.
  2. La imagen ejecutable es de 64 bits.
  3. Un valor devuelto por alguna llamada a PInvoke y almacenado como int es en realidad mayor que 32 bits.
+1

si ejecuta la asignación de memoria de arriba hacia abajo, entonces puede garantizar la condición 3, que es muy útil al desarrollar –

+0

Su publicación es la de Jon. Desearía poder hacer algo para llamar más la atención. ¡Había tocado fondo con un componente que se comportaba erráticamente y tu visión me puso en el camino correcto! Me has alegrado el día. No. Mi semana. Posiblemente todo mi mes para decir lo menos. ¡Gracias de nuevo! P.S .: Aquí hay un ejemplo de cómo las cosas pueden ir al sur con int vs IntPtr: http://stackoverflow.com/questions/15548016/global-keyboard-hook/36188346#36188346 – xDisruptor