Почему приведение большого двойного значения в sbyte возвращает 0 в C#?
На самом деле я тестирую поведение приведения в C# в непроверенном контексте. Как сказано в документации, в неконтролируемом контексте приведение всегда выполняется успешно. Но иногда, в частных случаях, приведение одного конкретного типа к другому дает неожиданный результат.
Например, я протестировал три приведения типа double to sbyte:
var firstCast = (sbyte) -129.83297462979882752; // Result : 127.
var secondCast = (sbyte) -65324678217.74282742874973267; // Result : 0.
var thirdCast = (sbyte) -65324678216.74282742874973267; // Result : 0.
Чтобы было ясно, разница между вторым и третьим дублем просто 1
(secondDouble - firstDouble = 1
). В этом случае результаты кастинга кажутся всегда одинаковыми.0
для любого "большого" двойного значения.
У меня вопрос: почему второй и третий забросы приводят к 0
? Я искал ответ в документации по C#, но не нашел.
Я протестировал это с помощью.Net Framework 4.7.2.
1 ответ
Согласно спецификации языка C#,
Для преобразования из типа float или double в целочисленный тип обработка зависит от контекста проверки переполнения, в котором происходит преобразование:
Без использования checked
или unchecked
операторов, по умолчанию контекст проверки переполнения не отмечен, поэтому мы смотрим на:
В непроверенном контексте преобразование всегда выполняется успешно и происходит следующим образом.
Если значение операнда - NaN или бесконечно, результатом преобразования является неопределенное значение целевого типа.
В противном случае исходный операнд округляется в сторону нуля до ближайшего целого значения. Если это целое значение находится в диапазоне целевого типа, тогда это значение является результатом преобразования.
В противном случае результатом преобразования будет неопределенное значение типа назначения.
Здесь значения не являются ни NaN, ни бесконечными. При округлении до нуля они не попадают в допустимый диапазонsbyte
, который составляет от -128 до 127, поэтому применяется последний пункт маркера, что означает, что результат такого преобразования не указан.
Другими словами, результат этого приведения зависит от того, какой компилятор вы используете. Разные компиляторы могут делать разные вещи, и они по-прежнему будут называться компиляторами C#. Скорее всего, какой бы компилятор вы ни использовали, просто подумал, что было бы лучше вернуть 0 для преобразования, когда значение для преобразования очень далеко от нижней / верхней границы.