По крайней мере, на первый взгляд, это не вопрос переполнения 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;
}
Спасибо всем за комментарии! многому научился
(int)yourUint
. Если значение больше, чем int.MaxValue, оно автоматически станет отрицательным значением int, например. uint.MaxValue станет int -1. - person ckuri   schedule 13.01.2019const
передint intMaxValue = int.MaxValue;
Почему вы думаете, что это происходит? - person mjwills   schedule 13.01.2019uint
. Если бы вы проводили сравнения в SQL, вы бы обнаружили, что(int)1 > (int)uint.MaxValue
(неправильный ответ). - person Ben Voigt   schedule 13.01.2019int.MinValue
вместо вычитанияint.MaxValue
и еще 1. - person Ben Voigt   schedule 13.01.2019v ^ int.MinValue
,v + int.MinValue
илиv - int.MaxValue - 1
. Порядок не сохраняется в предложении, сделанном ckuri, которое было просто преобразовано в int без вычитания, без преобразования диапазонов. Он специально говорил о сопоставленииuint.MaxValue
с-1
(снова прочитайте его комментарий).Приведение, а также переворачивание старшего бита сопоставляетuint.MaxValue
сint.MaxValue
, как вы думаете. - person Ben Voigt   schedule 13.01.2019int
неявно преобразуется в типuint
, когда она находится в диапазонеuint
(int.MaxValue
находится в диапазонеuint
). A constant_expression типаint
можно преобразовать в типsbyte
,byte
,short
,ushort
,uint
илиulong
при условии, что значение constant_expression находится в пределах диапазона целевого типа. - person user4003407   schedule 13.01.2019