2011-07-17 22 views
27

Al traducir la API de Windows (incluidos los tipos de datos) a P/Invoke, ¿debo reemplazar DWORD con int o uint?¿Debería DWORD asignar a int o uint?

la cual es normalmente sin firmar, pero veo a la gente usando int todas partes en su lugar (es sólo debido a la advertencia CLS? even the .NET Framework itself hace this), y por lo que nunca estoy realmente seguro de cuál es la correcta para su uso.

Respuesta

40

Bueno according to the MSDNDWORD es un entero sin signo con un rango de 0 a 4294967295.

Así que lo ideal es que reemplazarlo con uint en lugar de int.

Sin embargo, como ha detectado uint no cumple con CLS, de modo que si su método es público, debe usar int y realizar la conversión. El corolario de eso es que si su método no se usa fuera de su ensamblaje, debe marcarlo como internal en lugar de public. Entonces podrás usar un uint.

+0

Creo que lo que me preocupa es que es (1) incompatibles con el marco, y (2) no compatible con CLS. ¿Debería simplemente ignorar eso? – Mehrdad

2

No tiene firma así que asócielo a uint.

1

Un DWORD es, por definición de (Microsoft), un entero de 32 bits sin signo. Debe correlacionarse con el tipo que use su compilador para representar eso.

En la actualidad, lo más probable es que sea una int sin firmar, pero esa no es una implementación portátil. Sé que estás usando C#, pero para darle un ejemplo en un idioma que estoy más familiarizado, una implementación típica en C podría ser: se aplica

advertencia cumplimiento
#if defined(SOME_HARDWARE_IMPLEMENTATION) 
#define DWORD unsigned int 
#elif #defined(SOME_OTHER_IMPLEMENTATION) 
#define DWORD unsigned long 
#elif #defined(YET_ANOTHER_IMPLEMENTATION) 
#define DWORD something_else 
#else 
#error Unsupported hardware; cannot map DWORD 
#endif 
+0

Sin embargo, en C#, 'uint' y' int' son enteros de 32 bits. Sin embargo, tiene razón en que en C, los tipos de datos primitivos como 'int' y' long' no son consistentes entre los compiladores. Sin embargo, esto solo será un problema si 'DWORD' se usa en una función o API no definida por Microsoft, donde según su definición,' DWORD' es un entero sin signo de 32 bits. –

+0

C int y long son siempre de 32 bits en Windows –

1

El CLS sólo si el P/Invoke El método es visible fuera del ensamblado, lo que generalmente significa que la llamada es pública. Si el método no es visible externamente, entonces es aceptable usar uint.

2

Usar int. La razón de ser, si cambio "AutoRestartShell" con una variable de uint:

regKey.SetValue("AutoRestartShell", uintVariable); 

el tipo de datos en el Editor de Registro cambios a "REG_SZ". Si pido que el valor a ser devuelto con:

regKey.GetValue("AutoRestartShell"); 

una cadena es retornada.

Sin embargo, si yo cambio "AutoRestartShell" con una variable int :

regKey.SetValue("AutoRestartShell", intVariable); 

El tipo de datos se mantiene como "REG_DWORD".

¿Por qué sucede esto? Ni idea. Todo lo que sé es que sí. La lógica ciertamente nos diría que debería usarse, pero eso cambia el tipo de datos que no queremos.

+0

¿Cómo se relaciona el comportamiento o una parte de .NET completamente ajena a la clasificación de un tipo WinApi? – IllidanS4

+0

Por la misma razón que dos aplicaciones no pueden comunicarse entre sí enviando enteros donde el otro espera cadenas y viceversa. En cuanto a si uint o int marcarían una diferencia real aquí, no lo sé. Fue solo una observación. Pensé que era mejor no cambiar lo que no necesita ser cambiado. – Rehaan

+0

Parece que el culpable es el método privado * CalculateValueKind *. Simplemente no reconoce 'uint', pero tampoco conoce' short' u otros tipos numéricos. Pero veo el punto: la API pública debe manejar los tipos que cumplen con CLS de manera más importante que los tipos que no cumplen con CLS. El CLR en realidad no diferencia entre un 'int' y' uint'. – IllidanS4

0

Lamentablemente, leer registro debe utilizar de otro modo int tirar exception.this código de Microsoft:

private static void Get45or451FromRegistry() 
{ 
    using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) { 
     if (ndpKey != null && ndpKey.GetValue("Release") != null) { 
      Console.WriteLine("Version: " + CheckFor45DotVersion((int) ndpKey.GetValue("Release"))); 
     } 
     else { 
     Console.WriteLine("Version 4.5 or later is not detected."); 
     } 
    } 
} 

aunque liberación es REG_DWORD

Cuestiones relacionadas