Должна ли DWORD сопоставлять int или uint?
При переводе API Windows (включая типы данных) в P/Invoke следует заменить DWORD на int
или uint
?
Обычно он без знака, но я вижу людей, использующих int
везде (это просто из-за предупреждения CLS? даже сама .NET Framework делает this), и поэтому я никогда не уверен, какой из них правильный.
Ответы
Ответ 1
Ну в соответствии с MSDN DWORD
- целое число без знака с диапазоном от 0 до 4294967295.
В идеале вы должны заменить его uint
, а не int
.
Однако, поскольку вы заметили, что uint
не соответствует CLS, поэтому, если ваш метод является общедоступным, вы должны использовать int
и выполнить преобразование. Следствием этого является то, что если ваш метод не используется вне вашей сборки, вы должны пометить его как internal
, а не public
. Тогда вы сможете использовать uint
.
Ответ 2
Без знака, сопоставьте его с uint
.
Ответ 3
Использовать int. Причина в том, что если я изменяю "AutoRestartShell" с переменной uint:
regKey.SetValue("AutoRestartShell", uintVariable);
тип данных в Редакторе реестра изменяется на "REG_SZ" . Если я попрошу вернуть это значение с помощью:
regKey.GetValue("AutoRestartShell");
возвращается строка.
Если, однако, я изменяю "AutoRestartShell" с переменной int:
regKey.SetValue("AutoRestartShell", intVariable);
Тип данных остается "REG_DWORD" .
Почему это происходит? Без понятия. Все, что я знаю, это так. Логика наверняка сообщит нам, что uint следует использовать, но это меняет тип данных, который нам не нужен.
Ответ 4
DWORD по определению (Microsoft) представляет собой 32-битовое целое без знака. Он должен сопоставляться с тем типом, который ваш компилятор использует для представления.
В наши дни это, скорее всего, unsigned int, но это не переносная реализация. Я знаю, что вы используете С#, но чтобы дать вам пример на языке, с которым я больше знаком, типичная реализация на C может быть:
#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
Ответ 5
Предупреждение о соответствии CLS применяется только в том случае, если метод P/Invoke отображается вне сборки, что обычно означает, что вызов является общедоступным. Если метод внешне не виден, допустимо использовать uint
.
Ответ 6
К сожалению, чтение реестра должно использовать int, иначе бросать exception.this код 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.");
}
}
}
хотя релиз - REG_DWORD