2014-09-11 6 views
18

Может быть, я нахожусь в основах, но я все еще изучаю эту вещь C# в школе. Я понимаю, что если я добавлю 1 к максимальному значению Integer, который 32 бит, результат будет отрицательным. Я прочитал, что C# предлагает проверенные и непроверенные ключевые слова для обработки переполнения. Проверенное ключевое слово - это что-то, я нашел полезным, но как насчет неконтролируемого ключевого слова? Я действительно не могу найти не очень полезное использование для блока unchecked -keyworded. Есть ли? Как разные два подхода отличаются друг от друга?unchecked -keyword в C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Practice_6 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int value = Int32.MaxValue; 
      value++; 
      //Approach 1 to make a decision 
      if (value > Int32.MaxValue) { 
       //Do something 
      } 
      value = Int32.MaxValue; 
      //Approach 2 to make a decision 
      unchecked { 
       value++; 
       //Do something 
      } 
      //What's the difference between these two approaches to handle overflow? 
    } 
} 
+0

'if (value> Int32.MaxValue)' --- было ли это условие истинным для некоторого значения «целое»? – zerkms

+1

Пользовательские реализации 'GetHashCode' являются хорошими примерами сценариев, где' unchecked' может быть полезен, т. Е. Http://stackoverflow.com/a/263416/1644813 –

+0

if (value> INT32.MaxValue) returs True, я думаю –

ответ

4

Я не совсем уверен, что последствия производительности checked и unchecked. Теоретически unchecked должен быть более совершенным, и это контекст по умолчанию. Если вы не повесите границы целых типов для какого-то специального алгоритма/бизнес-логики и т. Д., Использование checked редко необходимо/полезно/читаемо.

Как я уже говорил, unchecked является контекстом по умолчанию, так зачем вам нужно ключевое слово unchecked? Можно было бы четко указать тип контекста, в котором существует большое использование контекстов checked. Другое заключается в использовании unchecked контекста в checked контексте:

checked { 
    int a = 5 + 1231; 

    unchecked { 
     a += 221; 
    } 
} 

Ваш вопрос может быть то, почему контекст по умолчанию снят. Я предполагаю, что это выбор дизайна от Microsoft.

Их отличие состоит в том, что контекст checked проверяет, существует ли переполнение для каждой арифметической операции и возникает исключение, если есть переполнение.

+0

+1 для ответа на фактический вопрос – har07

2

Из MSDN причина использования бесконтрольно будет следующим

Поскольку проверка переполнения требует времени, использование непроверенного кода в ситуациях, когда существует никакой опасности переполнения не может повысить производительность. Однако, если переполнение является возможностью, необходимо использовать проверенную среду.

+0

Хотя цитируемая информация может быть полезной в некотором роде, я думаю, что OP спрашивает о том, когда используется ключевое слово 'unchecked' потому что контекст по умолчанию уже «не отмечен», и это не отвечает на вопрос – har07

+0

Это не обязательно значение по умолчанию, если/checked используется, как правило, но не во всех случаях. –

0

Измените коды:

int value = int.MaxValue; 
    unchecked 
    { 
    value++; 
    } 
    Console.WriteLine(value); 
    value = int.MaxValue; 
    checked 
    { 
    value++; // this will raise OverflowException 
    } 

и вы увидите разницу.

+0

Это не отвечает на вопрос. Вопрос заключается в различии между * использованием 'unchecked' * и * не с использованием какого-либо ключевого слова * – har07

+2

_не использовать любое ключевое слово_ может быть похоже на _using checked_ или _using unchecked_, в зависимости от настроек компилятора. См. Http://msdn.microsoft.com/en-us/library/khy08726.aspx –

30

ОБНОВЛЕНИЕ: Этот вопрос был 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; 
    } 
} 

«непроверенный» подчеркивает читателю, что мы ожидаем, что множительной и добавления хэш-коды могут переполняться, и что это нормально.

Ваш второй вопрос:

В чем разница между этими двумя подходами для обработки переполнения?

Хороший вопрос.

Если в вашем проверочном контексте вы имеете в виду: Я ожидаю, что арифметика всегда будет в пределах границ; если это не так, то моя программа имеет серьезную ошибку и должна быть прервана до того, как она наносит больше вреда миру, тогда вы не должны вообще выполнять проверку переполнения, потому что переполнений нет. Любое исключение должно прекратить выполнение программы; проверенный контекст просто заставляет выполнение работать, чтобы проверить правильность вашего кода.

Если в зарегистрированном контексте вы имеете в виду я требую арифметики быть в пределах границ, но я получил эти данные из ненадежного источника, и я слишком ленив, чтобы сделать проверку диапазона на нем, то вы должны поймать исключение. Однако,, лучшей практикой было бы проводить проверку диапазона и давать более значимую ошибку, если данные вне диапазона, чем для того, чтобы среда выполнения обнаружила проблему и выбрала исключение переполнения. Я бы настоятельно рекомендовал проверку диапазона, а не исключение; не ленитесь.

+0

Мое предпочтение с 'unchecked' состояло бы в том, чтобы сфокусировать его как можно ближе (только последнее выражение). Есть ли какая-то особая причина для более широкого охвата? Кроме того, если это, например, прием данных из двоичного файла, например, содержит смесь базовых и относительных значений, что можно ожидать от кода, если сумма относительного значения и переполнение базы? Если наиболее вероятный сценарий, когда это произойдет, будет пытаться загрузить файл с неправильным типом (подразумевая, что файл и любые данные, прочитанные до сих пор, должны считаться бессмысленными, но система в остальном отлично) ... – supercat

+0

.. . Каковы практические различия между бросанием исключения, отличным от OverflowException, перехват OverflowException и бросание чего-то другого, бросание OverflowException и ожидание того, что вызывающий объект предположил, что OverflowException подразумевает попытку загрузить то, что не было допустимым файлом ожидаемого типа, или позволяя происходит переполнение ExceptionException (с тем же ожиданием re caller)? – supercat

+6

+1 за упоминание бесполезности оператора унарного пользователя –

4

Не следует ожидать, что надлежащим образом написанный код зависит от того, скомпилирован ли проект с отмеченным или непроверенным по умолчанию. Код, в котором неочевидное арифметическое поведение обертывания может представлять опасность для безопасности или стабильности системы, должно быть выполнено в контексте checked. Код, который опирается на обертывание арифметического поведения, должен быть выполнен в контексте unchecked.Код общего назначения, в котором не ожидается арифметических переполнений, но имел бы ограниченные последствия, если они это сделали, должен быть скомпилирован с использованием настройки уровня проекта. Затем параметр уровня проекта может быть установлен или отменен как компромисс между скоростью выполнения и своевременным захватом ошибок.

Если неожиданные переполнения происходят где-либо, код будет работать быстрее в непроверенном режиме. Если, однако, некоторые вычисления дают поддельные значения, и неясно, почему может помочь перекомпиляция с проверкой переполнения. Это заставит код работать медленнее, но будет ловушка при первом ошибочном вычислении. Однако переключение проекта в режим проверки для такой цели будет возможно только в том случае, если те части проекта, которые полагаются на арифметическое поведение обертывания, выполняются в явном контексте unchecked. В противном случае переключение режимов уровня проекта просто полностью разрушит программу.