Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DWORD应该映射到int还是uint?_C#_.net_Winapi_Pinvoke_Dword - Fatal编程技术网

C# DWORD应该映射到int还是uint?

C# DWORD应该映射到int还是uint?,c#,.net,winapi,pinvoke,dword,C#,.net,Winapi,Pinvoke,Dword,在将Windows API(包括数据类型)转换为p/Invoke时,我应该用int或uint替换DWORD吗 它通常是无符号的,但我看到人们到处都在使用int(这是因为CLS警告吗?确实如此),所以我从来都不确定使用哪个是正确的。它是无符号的,所以将它映射到uint嗯DWORD是一个范围为0到4294967295的无符号整数 因此,理想情况下,您应该将其替换为uint,而不是int 但是,正如您所发现的那样,uint不符合CLS,因此如果您的方法是公开可见的,您应该使用int并进行转换。由此推论

在将Windows API(包括数据类型)转换为p/Invoke时,我应该用
int
uint
替换DWORD吗


它通常是无符号的,但我看到人们到处都在使用
int
(这是因为CLS警告吗?确实如此),所以我从来都不确定使用哪个是正确的。

它是无符号的,所以将它映射到
uint
DWORD
是一个范围为0到4294967295的无符号整数

因此,理想情况下,您应该将其替换为
uint
,而不是
int

但是,正如您所发现的那样,
uint
不符合CLS,因此如果您的方法是公开可见的,您应该使用
int
并进行转换。由此推论,如果您的方法未在程序集外部使用,则应将其标记为
internal
,而不是
public
。然后您就可以使用
uint

根据(微软)的定义,DWORD是一个无符号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

CLS compliance警告仅在p/Invoke方法在程序集外部可见时适用,这通常意味着调用是公共的。如果该方法外部不可见,则可以使用
uint

使用int。原因是,如果我使用uint变量更改“AutoRestartShell”

regKey.SetValue("AutoRestartShell", uintVariable);
regKey.SetValue("AutoRestartShell", intVariable);
注册表编辑器中的数据类型更改为“REG_SZ”。如果我要求返回该值,并附带:

regKey.GetValue("AutoRestartShell");
返回一个字符串

但是,如果我使用int变量更改了“AutoRestartShell”

regKey.SetValue("AutoRestartShell", uintVariable);
regKey.SetValue("AutoRestartShell", intVariable);
数据类型保持为“REG\u DWORD”


为什么会发生这种情况?不知道。我所知道的是它确实如此。逻辑当然会告诉我们应该使用uint,但这会改变我们不想要的数据类型。

遗憾的是,读取注册表必须使用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.");
      } 
    }
}

尽管根据官方映射表,release是REG_DWORD

但DWORD对应于
系统。UInt32
在C中。

但是,在C中,
uint
int
是32位整数。但是,在C语言中,诸如
int
long
之类的基本数据类型在编译器之间并不一致,这是正确的。但是,只有在Microsoft未定义的函数或API中使用
DWORD
时,这才是问题所在,根据定义,
DWORD
是32位无符号整数。在Windows上,C int和long始终是32位的。我想我担心的是,(1)与框架不一致,(2)不符合CLS。我应该忽略这一点吗?.NET的行为或完全不相关的部分与封送WinApi类型有什么关系?原因相同,两个应用程序不能通过一个发送整数相互通信,而另一个需要字符串,反之亦然。至于uint或int是否会在这里产生实际的影响,我不知道。这只是一个观察。我认为最好不要改变那些不需要改变的东西。看起来罪魁祸首是私人的CalculateValueKind方法。它只是不确认
uint
,但也不知道
short
或其他数字类型。但是我认为点公共API应该比不符合CLS的类型更重要地处理符合CLS的类型。CLR实际上不区分
int
uint