C# 为什么从uint中减去int.MaxValue与从uint中减去int类型变量不同?

C# 为什么从uint中减去int.MaxValue与从uint中减去int类型变量不同?,c#,.net,int,uint,C#,.net,Int,Uint,至少在表面上,这不是一个int或uint溢出的问题。据我所知,这些值只重叠了约一半,而且范围相等。事实上,我正指望着这一点 背景:有一个返回uint的DotNet CRC哈希算法,我需要将其转换为sql存储(缺少uint)。尽管起点和终点不同,但由于两者的总范围相等,因此应始终可以进行此转换。不必担心逆转转换。我将其调试为Dotnet4.0和4.6.1,结果相同 我很困惑: 在下面的代码示例中: intForSqlStorageOK成功。 但是,intForSqlStorageFail1引发运行

至少在表面上,这不是一个int或uint溢出的问题。据我所知,这些值只重叠了约一半,而且范围相等。事实上,我正指望着这一点

背景:有一个返回uint的DotNet CRC哈希算法,我需要将其转换为sql存储(缺少uint)。尽管起点和终点不同,但由于两者的总范围相等,因此应始终可以进行此转换。不必担心逆转转换。我将其调试为Dotnet4.0和4.6.1,结果相同

我很困惑: 在下面的代码示例中:
intForSqlStorageOK成功。
但是,intForSqlStorageFail1引发运行时异常。
他们有什么不同


谢谢大家的评论!学习了很多

根据,
int.MaxValue
可以隐式转换为
uint
类型,而非常量
int
表达式不能,因为编译时编译器不知道
int
表达式的值是否在
uint
类型的范围内

如果应用运算符解析规则,则会看到,
uIntToBeStoredInSql-intMaxValue-1
被解释为
(长)uIntToBeStoredInSql-(长)intMaxValue-1L
,总值
-2146892577L
(在
int
类型范围内)


uintobestoredinsql-int.MaxValue-1
被解释为
uintobestoredinsql-(uint)int.MaxValue-1u
,总值
2148074719u
(不在
int
类型的范围内)在
未选中的
上下文和
已选中的
上下文中的
溢出异常
异常。

您不需要手动转换输入范围,只需执行
(int)yourUint
。如果该值大于int.MaxValue,它将自动变为负的int值,例如uint.MaxValue将变为int-1。@ckuri-在我的头脑中仍然是反直觉的-但它可以工作!谢谢@ckuri:除非您需要在SQL中进行比较,否则在这种情况下还需要对MSB/符号位进行异或以保留顺序。我将给您一些思考,看看这是否能让您更接近理解。如果将
const
放在
int intMaxValue=int.MaxValue之前,代码执行会发生什么情况你认为它为什么会这样做?@mjwills-代码做了什么?你期望它做什么?你为什么期望它会这样做?
{
    uint uIntToBeStoredInSql = 591071; //CRC32 hash result
    int intMaxValue = int.MaxValue;
    int intForSqlStorageOK = Convert.ToInt32(uIntToBeStoredInSql - intMaxValue - 1);

    //System.OverflowException: 'Value was either too large or too small for an Int32.'
    int intForSqlStorageFail1 = Convert.ToInt32(uIntToBeStoredInSql - int.MaxValue - 1);
    int intForSqlStorageFail2 = Convert.ToInt32(uIntToBeStoredInSql - Convert.ToUInt32(int.MaxValue) - 1);
    int intForSqlStorageFail3 = checked(Convert.ToInt32(uIntToBeStoredInSql - int.MaxValue - 1));
    int intForSqlStorageFail4 = unchecked(Convert.ToInt32(uIntToBeStoredInSql - int.MaxValue - 1));
    int intForSqlStorageFail5; //??? probably many others ???

    ///this SO led to this workaround, which is just clobbering the problem by adding memory. doesn't explain the difference above.
    ///https://stackoverflow.com/questions/26386201/subtracting-uint-and-int-and-constant-folding
    int intForSqlStorageOK2 = Convert.ToInt32(Convert.ToInt64(uIntToBeStoredInSql) - int.MaxValue - 1);

    ///Thanks ckuri in comments - this is way more terse and somehow still arrives at same result
    int intForSqlStorageOK3 = (int)uIntToBeStoredInSql - intMaxValue - 1;
    int intForSqlStorageOK4 = (int)uIntToBeStoredInSql - int.MaxValue - 1;

}