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

Why is subtracting int.MaxValue from uint different from subtracting an int typed variable from uint?

至少从表面上看,这不是int溢出的问题,也不是uint溢出的问题。我知道这些值只重叠了一半,而且范围是相等的。事实上,我指望着那个。

背景: 有一个 returns uint 的 DotNet CRC 哈希算法,我需要将其转换为存储在 sql 中(缺少一个单位)。这种转换应该始终是可能的,因为两者的总范围是相等的,即使起点和终点不同。无需担心反转转换。我将其调试为 DotNet 4.0 和 4.6.1,结果相同。

我在这里莫名其妙:

在下面的代码示例中:
intForSqlStorageOK 成功。
但是 intForSqlStorageFail1 抛出运行时异常。
他们有什么不同?


{
    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.
    ///
    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;

}

感谢大家的评论!学到很多

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

如果您应用运算符解析规则,那么您会看到,uIntToBeStoredInSql - intMaxValue - 1 被解释为 (long)uIntToBeStoredInSql - (long)intMaxValue - 1L,总值 -2146892577L(在 [=12= 的范围内) ]类型)。

虽然 uIntToBeStoredInSql - int.MaxValue - 1unchecked 上下文中被解释为 uIntToBeStoredInSql - (uint)int.MaxValue - 1u,总值 2148074719u(不在 int 类型的范围内)并且 OverflowException checked 上下文中的异常。