Должен ли DWORD отображаться на int или uint? - PullRequest
30 голосов
/ 17 июля 2011

При переводе Windows API (включая типы данных) в P / Invoke я должен заменить DWORD на int или uint?

Обычно он не подписан, но я вижу людей, использующих int вездевместо этого (это только из-за предупреждения CLS? даже сама .NET Framework делает это ), и поэтому я никогда не уверен, какой из них правильный.

Ответы [ 6 ]

43 голосов
/ 17 июля 2011

Скважина по MSDN DWORD - целое число без знака с диапазоном от 0 до 4294967295.

Так что в идеале вы должны заменить его на uint вместо int.

Однако, как вы заметили, uint не соответствует CLS, поэтому, если ваш метод общедоступен, вы должны использовать int и выполнить преобразование. Следствием этого является то, что если ваш метод не используется вне вашей сборки, вы должны пометить его как internal, а не public. Тогда вы сможете использовать uint.

2 голосов
/ 17 марта 2017

Используйте int.Причина в том, что при изменении "AutoRestartShell" с помощью переменной uint :

regKey.SetValue("AutoRestartShell", uintVariable);

тип данных в Редакторе реестра изменится на "REG_SZ" .Если я запрашиваю, чтобы это значение было возвращено с:

regKey.GetValue("AutoRestartShell");

a string , то возвращается.

Если, однако, я изменяю "AutoRestartShell" с переменной int :

regKey.SetValue("AutoRestartShell", intVariable);

Тип данных сохраняется как "REG_DWORD" .

Почему это происходит?Без понятия.Все, что я знаю, это то, что он делает.Логика, конечно, говорит нам, что следует использовать uint, но это меняет тип данных, который нам не нужен.

2 голосов
/ 17 июля 2011

Это без знака, поэтому сопоставьте его с uint.

1 голос
/ 17 июля 2011

Предупреждение о соответствии CLS применяется только в том случае, если метод P / Invoke видим вне сборки, что обычно означает, что вызов является общедоступным.Если метод не виден снаружи, тогда допустимо использовать uint.

1 голос
/ 17 июля 2011

DWORD, по определению (Microsoft), 32-разрядное целое число без знака.Он должен соответствовать тому типу, который ваш компилятор использует для представления этого.

В наши дни это, скорее всего, int без знака, но это не переносимая реализация.Я знаю, что вы используете C #, но, чтобы дать вам пример на языке, с которым я более знаком, типичная реализация в 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
0 голосов
/ 12 октября 2017

К сожалению, чтение реестра должно использовать int, в противном случае выдает исключение. Этот код 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

...