ОБНОВЛЕНИЕ: Этот вопрос был the subject of my blog in April 2015; спасибо за интересный вопрос!
Ваш первый вопрос:
checked
ключевое слово полезно, но как насчет unchecked
ключевого слова? Я действительно не могу найти для этого пользы. Есть ли?
У команды разработчиков C# нет привычки добавлять функции, которые не имеют никакого отношения к языку. (За исключением оператора унарного плюса, самого бесполезного оператора в мире).
Непроверенное ключевое слово имеет два основных варианта использования.
Во-первых, Постоянная целочисленная арифметика всегда проверяется по умолчанию. Это может раздражать.Предположим, например, у вас есть некоторый Interop код, и вы хотите, чтобы создать константу для HRESULT E_FAIL:
const int E_FAIL = 0x80004005;
Это ошибка, потому что номер слишком велик, чтобы поместиться в int
. Но вы, возможно, не захотите использовать uint
. Вы можете подумать, а я просто скажу
const int E_FAIL = (int)0x80004005;
Но это также является незаконной, так как постоянная арифметика включая преобразование всегда проверяются по умолчанию.
То, что вы должны сделать, это отключить проверяется постоянная арифметика через
const int E_FAIL = unchecked((int)0x80004005);
Во-вторых, арифметика по умолчанию для непостоянной целочисленной математики в C# снята, потому что это быстрее, а потому, что это то, что многие другие подобные языки. Однако C# позволяет поменять значение по умолчанию на проверочную арифметику для непостоянной целочисленной математики с помощью флага компилятора. Если вы это сделали, и вам нужно снова отменить его на временной основе, вам нужно использовать блок или синтаксис блока unchecked
.
Третий вариант использования - использовать неконтролируемый блок как форму самодокументирующего кода, чтобы сказать: «Я знаю, что операция, которую я здесь делаю, может переполняться, и все в порядке со мной». Например, я часто пишу что-то вроде:
int GetHashCode()
{
unchecked
{
int fooCode = this.foo == null ? 0 : this.foo.GetHashCode();
int barCode = this.bar == null ? 0 : this.bar.GetHashCode();
return fooCode + 17 * barCode;
}
}
«непроверенный» подчеркивает читателю, что мы ожидаем, что множительной и добавления хэш-коды могут переполняться, и что это нормально.
Ваш второй вопрос:
В чем разница между этими двумя подходами для обработки переполнения?
Хороший вопрос.
Если в вашем проверочном контексте вы имеете в виду: Я ожидаю, что арифметика всегда будет в пределах границ; если это не так, то моя программа имеет серьезную ошибку и должна быть прервана до того, как она наносит больше вреда миру, тогда вы не должны вообще выполнять проверку переполнения, потому что переполнений нет. Любое исключение должно прекратить выполнение программы; проверенный контекст просто заставляет выполнение работать, чтобы проверить правильность вашего кода.
Если в зарегистрированном контексте вы имеете в виду я требую арифметики быть в пределах границ, но я получил эти данные из ненадежного источника, и я слишком ленив, чтобы сделать проверку диапазона на нем, то вы должны поймать исключение. Однако,, лучшей практикой было бы проводить проверку диапазона и давать более значимую ошибку, если данные вне диапазона, чем для того, чтобы среда выполнения обнаружила проблему и выбрала исключение переполнения. Я бы настоятельно рекомендовал проверку диапазона, а не исключение; не ленитесь.
'if (value> Int32.MaxValue)' --- было ли это условие истинным для некоторого значения «целое»? – zerkms
Пользовательские реализации 'GetHashCode' являются хорошими примерами сценариев, где' unchecked' может быть полезен, т. Е. Http://stackoverflow.com/a/263416/1644813 –
if (value> INT32.MaxValue) returs True, я думаю –