将 Windows API(包括数据类型)转换为 P/Invoke 时,我应该将 DWORD 替换为int
oruint
吗?
它通常是未签名的,但我看到人们int
到处都在使用(仅仅是因为 CLS 警告吗?甚至 .NET Framework 本身也会这样做),所以我永远不确定哪个是正确的使用。
根据 MSDN, 它DWORD
是一个无符号整数,范围为 0 到 4294967295。
因此,理想情况下,您应该将其替换为uint
而不是int
.
但是,正如您所发现的那样,uint
它不符合 CLS,因此如果您的方法是公开可见的,您应该使用int
并进行转换。其必然结果是,如果您的方法未在程序集之外使用,则应将其标记为internal
而不是public
. 然后你就可以使用uint
.
它是未签名的,因此将其映射到uint
.
根据(Microsoft)的定义,DWORD 是一个无符号的 32 位整数。它应该映射到您的编译器用来表示它的任何类型。
现在它很可能是一个无符号整数,但这不是一个可移植的实现。我知道您使用的是 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
只有当 P/Invoke 方法在程序集外部可见时,CLS 合规性警告才适用,这通常意味着调用是公开的。如果该方法在外部不可见,则可以使用uint
.
使用整数。原因是,如果我用uint变量更改“AutoRestartShell” :
regKey.SetValue("AutoRestartShell", uintVariable);
注册表编辑器中的数据类型更改为"REG_SZ"。如果我要求返回该值:
regKey.GetValue("AutoRestartShell");
返回一个字符串。
但是,如果我用int变量更改“AutoRestartShell” :
regKey.SetValue("AutoRestartShell", intVariable);
数据类型保持为"REG_DWORD"。
为什么会这样?不知道。我所知道的是它确实如此。逻辑肯定会告诉我们应该使用 uint ,但这会改变我们不想要的数据类型。
可悲的是,读取注册表必须使用 int 否则抛出异常。这个微软代码:
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
根据官方平台调用数据类型映射表DWORD
对应System.UInt32
于C#中。