Lorsque je traduis l'API Windows (y compris les types de données) en P/Invoke, dois-je remplacer DWORD par int
ou uint
?
C'est normalement non signé, mais je vois des gens qui utilisent plutôt int
partout (est-ce juste à cause de l'avertissement de CLS? même le .NET Framework lui-même does this ), et je ne suis donc pas vraiment sûr est le bon à utiliser.
Bien selon le MSDNDWORD
est un entier non signé compris entre 0 et 4294967295.
Donc, idéalement, vous devriez le remplacer par uint
plutôt que int
.
Toutefois, comme vous avez constaté que uint
n'est pas conforme à CLS, si votre méthode est visible publiquement, vous devez utiliser int
et effectuer la conversion. Le corollaire à cela est que si votre méthode n'est pas utilisée en dehors de votre assembly, vous devez la marquer comme suit: internal
plutôt que public
. Ensuite, vous pourrez utiliser une uint
.
Utilisez int. Raison d'être, si je change "AutoRestartShell" avec un uint variable:
regKey.SetValue("AutoRestartShell", uintVariable);
le type de données dans Éditeur de registre change en "REG_SZ" . Si je demande que cette valeur soit renvoyée avec:
regKey.GetValue("AutoRestartShell");
un string est renvoyé.
Si, toutefois, je change "AutoRestartShell" avec un int variable:
regKey.SetValue("AutoRestartShell", intVariable);
Le type de données reste en tant que "REG_DWORD" .
Pourquoi cela arrive-t-il? Aucune idée. Tout ce que je sais, c'est que c'est le cas. La logique nous dirait certainement que uint devrait être utilisé mais que cela change le type de données que nous ne voulons pas.
C'est non signé alors mappez-le sur uint
.
Selon la définition (de Microsoft), un DWORD est un entier 32 bits non signé. Il devrait correspondre au type utilisé par votre compilateur pour le représenter.
De nos jours, il s'agit probablement d'un entier non signé, mais ce n'est pas une implémentation portable. Je sais que vous utilisez C #, mais pour vous donner un exemple dans un langage que je connais mieux, une implémentation typique en C pourrait être:
#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
L'avertissement de conformité CLS s'applique uniquement si la méthode P/Invoke est visible à l'extérieur de l'assembly, ce qui signifie généralement que l'appel est public. Si la méthode n'est pas visible de l'extérieur, il est acceptable d'utiliser uint
.
Malheureusement, read Registry doit utiliser int, sinon, lève une exception. Ce code 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.");
}
}
}
bien que la version soit REG_DWORD