C#-UInt32对Int32有些奇怪 背景

C#-UInt32对Int32有些奇怪 背景,c#,unsigned,signed,C#,Unsigned,Signed,我在C#工作,通常为嵌入式项目编写支持程序。我继承了一个远去的人的项目,这是我的一个客户使用的一个程序,通过RS-232下载英特尔十六进制文件并上传到他们的一些主板上。多年来,这个程序对他们来说运行良好,但对于我正在开发的新董事会来说,情况并非如此,需要进行一些修改 问题 我打开项目,发现了问题。新电路板在0x90000000-0x9007FFFF范围内的地址处生成一些数据,而C代码使用int类型作为地址数据;已签名,未正确处理0x8000000上的地址。到目前为止,一切顺利。但后来我变得骄傲起

我在C#工作,通常为嵌入式项目编写支持程序。我继承了一个远去的人的项目,这是我的一个客户使用的一个程序,通过RS-232下载英特尔十六进制文件并上传到他们的一些主板上。多年来,这个程序对他们来说运行良好,但对于我正在开发的新董事会来说,情况并非如此,需要进行一些修改

问题 我打开项目,发现了问题。新电路板在
0x90000000-0x9007FFFF
范围内的地址处生成一些数据,而C代码使用
int
类型作为地址数据;已签名,未正确处理
0x8000000
上的地址。到目前为止,一切顺利。但后来我变得骄傲起来

我决定清理代码,根据用法将所有“int”替换为Int16/UInt16/Int32/UInt32。虽然花了一段时间,但我认为这会使代码更清晰、更容易理解,并有望避免将来出现任何bug

该守则停止运作。这花了我一天的大部分时间,归结起来就是这样一句话:

currseg = (HexSegment)hex_segments[HashEntry];
HexSegment类型是一个结构(是的,是结构,不是类)

hex_段是一个哈希表

最后,HashEntry是一个“int”,也被制成一个
UInt32

在调试器中,我看到以下内容:

如果看不到图像,HashEntry的值为
0x00000000
。 如果我要求调试器查看
hex_段[0]
,我会得到一个带有合法数据的
MLV.HexSegment
。 如果我要求调试器查看
hex_段[HashEntry]
,我会得到null

HashEntry
更改为
Int32
修复了该问题


就像我说的,我是一个嵌入式程序员。对我来说,这是一个很大的谜。有人能解释为什么会这样吗?

因为哈希表是按对象而不是按int索引的

public virtual object this[object key] { get; set; }
因此,如果一个对象添加了键0作为Int32,那么它将不同于添加了0作为UInt32的对象

看看这个:

UInt32 index = 0;
Int32 index2 = 0;
Hashtable t = new Hashtable();

t.Add(index, new { name = "matt" });
t.Add(index2, new { name = "Matt" });

var obj = t[index];
var obj2 = t[index2];

Console.WriteLine(obj);
Console.WriteLine(obj2);

0x08000000
(int)还是
0x80000000
(uint)?我认为问题在于您将
HashEntry
的数据类型从
int
更改为
uint
。但是,您没有更改插入哈希表的代码,这仍然是一个
int
。如果您向调试器请求
hex_段[0U]
,您将得到null。(顺便说一句,
int
始终与
Int32
相同,
uint
始终与
UInt64
相同。一般做法是使用
int
/
uint
,而不是
Int32
/
UInt32
)哈希表不是泛型类型。键是一个对象。
int
uint
都是值类型,因此都可以使用,但它们不同,装箱的int为0与装箱的uint为0非常不同。他们之间没有任何转换的方法。我的猜测是,您正在将某些内容作为int(转换为装箱int)插入,并尝试使用uint(转换为装箱uint)获取它。尽管它们都是
zero
,但它们并不是相等的集合,这使得生活中更不容易出错。因为编译器知道查找总是使用
UInt32
完成的,所以它将确保除了
UInt32
之外不能使用任何东西,Hastable的文档
表示根据键的哈希代码组织的键/值对的集合。
但是如果在index和index2上调用
GetHashCode()
,则两者的结果都是0。所以我仍然不确定为什么会这样。它们是由散列码组织的,但是仍然有一个
等于
的签入,还有一个框int!=一个装箱的uint,即使它们有相同的哈希代码。我认为这就是他们所说的对象迷失:)。在任何动态类型语言中都会遇到相同的问题。您应该使用提供给您的类型系统来帮助避免此类事情。
UInt32 index = 0;
Int32 index2 = 0;
Hashtable t = new Hashtable();

t.Add(index, new { name = "matt" });
t.Add(index2, new { name = "Matt" });

var obj = t[index];
var obj2 = t[index2];

Console.WriteLine(obj);
Console.WriteLine(obj2);