At least on the surface, this is not a question about overflowing int nor uint. I understand the values overlap by only ~half, and the ranges are equal. In fact I'm counting on that.
Background: Have a DotNet CRC hash algorithm that returns an uint, and I need to convert that for storage in sql (which lacks an uint). This conversion should always be possible as the total range of both are equal, even though the start and end points are different. There is no concern about reversing the conversion. I Debuggered this as DotNet 4.0 and 4.6.1 with same results.
I'm baffled here:
In the code examples below:
intForSqlStorageOK is successful.
But intForSqlStorageFail1 throws a runtime exception.
What's different about them?
{
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;
}
Thanks everyone for commenting! learned alot