Sollte ich beim Übersetzen der Windows-API (einschließlich Datentypen) in P/Invoke DWORD durch int
oder uint
ersetzen?
Normalerweise ist es nicht signiert, aber ich sehe Leute, die stattdessen int
verwenden (liegt das nur an der CLS-Warnung? sogar am .NET Framework selbst macht dies ), und ich bin mir nie ganz sicher, welche ist der richtige zu verwenden.
Nun laut MSDNDWORD
ist eine vorzeichenlose Ganzzahl mit einem Bereich von 0 bis 4294967295.
Idealerweise sollten Sie es durch uint
anstelle von int
ersetzen.
Da Sie jedoch festgestellt haben, dass uint
nicht mit CLS kompatibel ist, sollten Sie, wenn Ihre Methode öffentlich sichtbar ist, int
verwenden und die Konvertierung durchführen. Die Folge davon ist, dass, wenn Ihre Methode nicht außerhalb Ihrer Assembly verwendet wird, Sie sie als internal
statt als public
markieren sollten. Dann können Sie eine uint
verwenden.
Verwenden Sie int. Grund ist, wenn ich "AutoRestartShell" mit einer uint Variable ändere:
regKey.SetValue("AutoRestartShell", uintVariable);
der Datentyp im Registry Editor ändert sich nach "REG_SZ" . Wenn ich darum bittet, dass dieser Wert mit zurückgegeben wird:
regKey.GetValue("AutoRestartShell");
ein String wird zurückgegeben.
Wenn ich jedoch "AutoRestartShell" mit einer int Variable ändere:
regKey.SetValue("AutoRestartShell", intVariable);
Der Datentyp bleibt als "REG_DWORD" .
Warum passiert das? Keine Ahnung. Ich weiß nur, dass es das tut. Logic würde uns sicherlich sagen, dass Uint verwendet werden sollte, aber das den Datentyp ändert, den wir nicht wollen.
Es ist nicht signiert, also ordnen Sie es uint
zu.
Ein DWORD ist nach Definition von Microsoft eine vorzeichenlose 32-Bit-Ganzzahl. Es sollte dem Typ entsprechen, den Ihr Compiler verwendet, um dies darzustellen.
Heutzutage ist es höchstwahrscheinlich ein unsigniertes int, aber das ist keine portable Implementierung. Ich weiß, dass Sie C # verwenden, aber um Ihnen ein Beispiel in einer mir bekannten Sprache zu geben, könnte eine typische Implementierung in C Folgendes sein:
#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
Die CLS-Konformitätswarnung gilt nur, wenn die P/Invoke-Methode außerhalb der Assembly sichtbar ist. Dies bedeutet im Allgemeinen, dass der Anruf öffentlich ist. Wenn die Methode von außen nicht sichtbar ist, kann uint
verwendet werden.
Leider muss die Leseregistrierung int verwenden, sonst eine Ausnahme auslösen.
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.");
}
}
}
obwohl das Release REG_DWORD ist