По крайней мере, на первый взгляд, это не вопрос переполнения ни int, ни uint. Я понимаю, что значения перекрываются только на половину, а диапазоны равны. На самом деле я рассчитываю на это.
Справочная информация: Есть алгоритм хэширования DotNet CRC, который возвращает uint, и мне нужно преобразовать его для хранения в sql (в котором отсутствует uint). Это преобразование всегда должно быть возможным, так как общий диапазон обоих одинаков, даже если начальная и конечная точки различны. Нет беспокойства об обратном преобразовании. Я отладил это как 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.
///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;
}
Спасибо всем за комментарии! узнал много