Throw c что это
Перейти к содержимому

Throw c что это

throw (Справочник по C#)

Сообщает о возникновении исключения во время выполнения программы.

Remarks

Синтаксис throw выглядит следующим образом:

где e — это экземпляр класса, производного от System.Exception. В следующем примере используется оператор throw для создания IndexOutOfRangeException, если аргумент, переданный в метод с именем GetNumber , не соответствует допустимому индексу внутреннего массива.

Затем вызывающие объекты метода используют блок try-catch или try-catch-finally для обработки исключения. В следующем примере показана обработка исключения, созданного методом GetNumber .

Повторный вызов исключения

throw можно также использовать в блоке catch для повторного создания исключения, обрабатываемого в блоке catch . В этом случае оператор throw не принимает операнд исключения. Это наиболее полезно, когда метод передает аргумент от вызывающего объекта в другой метод библиотеки, а метод библиотеки создает исключение, которое должно быть передано вызывающему объекту. Например, в следующем примере повторно создается исключение NullReferenceException, возникающее при попытке получить первый символ неинициализированной строки.

Можно также использовать синтаксис throw e в блоке catch , чтобы создать исключение, которое будет передано вызывающему объекту. В этом случае трассировка стека исходного исключения, которое доступно из свойства StackTrace, не сохраняется.

Выражение throw

Начиная с C# 7.0 throw можно использовать в качестве выражения, а также как оператор. Это позволяет вызывать исключения в контекстах, которые ранее не поддерживались. Сюда входит следующее.

Условный оператор. В следующем примере используется исключение throw для создания ArgumentException, если методу передается массив пустых строк. До выхода C# 7.0 эта логика должна была отображаться в операторе if / else .

Оператор объединения с NULL. В следующем примере выражение throw используется с оператором, принимающим значение NULL, для создания исключения, если строка, назначенная свойству Name является null .

Метод или лямбда, воплощающие выражение. В следующем примере показан метод, воплощающий выражение, который создает InvalidCastException, так как преобразование в значение DateTime не поддерживается.

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

Обработка исключений в C++

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

Темные дни С

Типичная функция, написанная на С, выглядит примерно так:

Выглядит не очень, не так ли? Вы целиком и полностью зависите от значений, которые возвращают вам функции и для каждой ошибки вам постоянно нужен код, который ее обрабатывает. Если вы, скажем, в функции работаете хотя бы с 10 указателями (рапределяете память, освобождаете ее и т.д.), то наверняка половину кода функции будет занимать код обработки ошибок. Такая же ситуация будет в коде, вызывающем эту функцию, так как здесь также нужно обработать все возвращаемые коды ошибок.

Try-catch-throw

Давайте же разберем основы обработки исключений в С++. Чтобы комфортно работать с исключениями в С++ вам нужно знать лишь три ключевых слова:

  • try (пытаться) — начало блока исключений;
  • catch (поймать) — начало блока, «ловящего» исключение;
  • throw (бросить) — ключевое слово, «создающее» («возбуждающее») исключение.

А теперь пример, демонстрирующий, как применить то, что вы узнали:

Если выполнить этот фрагмент кода, то мы получим следующий результат:

Теперь закоментируйте строку throw 1; и функция выдаст такой результат:

Как видите все очень просто, но если это применить с умом, такой подход покажется вам очень мощным средством обработки ошибок. Catch может «ловить» любой тип данных, так же как и throw может «кинуть» данные любого типа. Т.е. throw AnyClass(); будет правильно работать, так же как и catch (AnyClass &d) <>;.

Как уже было сказано, catch может «ловить» данные любого типа, но вовсе не обязательно при это указывать переменную. Т.е. прекрасно будет работать что-нибудь типа этого:

Так же можно «поймать» и все исключения:

Троеточие в этом случае показывает, что будут пойманы все исключения. При таком подходе нельзя указать имя переменной. В случае, если «кидаются» данные нестандартного типа (экземпляры определенных вами классов, структур и т.д.), лучше «ловить» их по ссылке, иначе вся «кидаемая» переменная будет скопирована в стек вместо того, чтобы просто передать указатель на нее. Если кидаются данные нескольких типов и вы хотите поймать конкретную переменную (вернее, переменную конкретного типа), то можно использовать несколько блоков catch, ловящих «свой» тип данных:

Создание» исключений

Когда возбуждается исключительная ситуация, программа просматривает стек функций до тех пор, пока не находит соответствующий catch. Если оператор catch не найден, STL будет обрабатывать исключение в стандартном обработчике, который делает все менее изящно, чем могли бы сделать вы, показывая какие-то непонятные (для конечного пользователя) сообщения и обычно аварийно завершая программу.

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

Перегрузка глобальных операторов new/delete

А сейчас хотелось бы отправить вас к статье «Как обнаружить утечку памяти». В ней рассказывается, как обнаружить неправильное управление распределением памяти в вашей программе. Вы можете спросить, при чем тут перегрузка операторов? Если перегрузить стандартные new и delete, то открываются широкие возможности по отслеживанию ошибок (причем ошибок часто критических) с помощью исключений. Например:

Это, на первый взгляд, кажется длиннее, чем стандартная проверка в С «а равен NULL?», однако если в программе выделяется десяток динамических переменных, то такой метод оправдывает себя.

Операторы throw без параметров

Итак, мы увидели, как новый метод обработки ошибок удобен и прост. Блок try-catch может содержать вложенные блоки try-catch и если не будет определено соответствующего оператора catch на текущем уровен вложения, исключение будет поймано на более высоком уровне. Единственная вещь, о которой вы должны помнить, — это то, что операторы, следующие за throw, никогда не выполнятся.

Такой метод может применяться в случаях, когда не нужно передавать никаких данных в блок catch.

Приложение

Приведем пример, как все вышеизложенное может быть использовано в конкретном приложении. Преположим, у вас в программе есть класс cMain и экземпляр этого класса Main: class cMain < public: bool Setup(); bool Loop(); // Основной цикл программы void Close(); >; cMain Main;

А в функции main() или WinMain() вы можете использовать этот класс как-нибудь так:

Основной цикл программы может выглядеть примерно так:

Заключение

Метод обработки исключений, приведенный в статье, является удобным и мощным средством, однако только вам решать, использовать его или нет. Одно можно скачать точно — приведенный метод облегчит вам жизнь. Если хотите узнать об исключениях чуть больше, посмотрите публикацию Deep C++ на сервере MSDN.

Операторы throw и finally

XYZ School

Исключение может быть сгенерировано вручную с помощью оператора throw. Ниже приведена общая форма такого генерирования:

где в качестве exceptOb должен быть обозначен объект класса исключений, производного от класса Exception. Ниже приведен пример программы, в которой демонстрируется применение оператора throw для генерирования исключения OverflowException:

Обратите внимание на то, что исключение OverflowException было сгенерировано с использованием ключевого слова new в операторе throw. Не следует забывать, что в данном случае генерируется конкретный объект, а следовательно, он должен быть создан перед генерированием исключения. Это означает, что сгенерировать исключение только по его типу нельзя. В данном примере для создания объекта OverflowException был автоматически вызван конструктор, используемый по умолчанию, хотя для генерирования исключений доступны и другие конструкторы.

Повторное генерирование исключений

Исключение, перехваченное в одном блоке catch, может быть повторно сгенерировано в другом блоке, чтобы быть перехваченным во внешнем блоке catch. Наиболее вероятной причиной для повторного генерирования исключения служит предоставление доступа к исключению нескольким обработчикам. Допустим, что один обработчик оперирует каким-нибудь одним аспектом исключения, а другой обработчик — другим его аспектом. Для повторного генерирования исключения достаточно указать оператор throw без сопутствующего выражения, как в приведенной ниже форме:

Не следует, однако, забывать, что когда исключение генерируется повторно, то оно не перехватывается снова тем же самым блоком catch, а передается во внешний блок catch. Пример:

Использование оператора throw

Как видите, исключение DivideByZeroException обрабатывается как во внутреннем блоке, так и во внешнем.

Использование блока finally

Иногда требуется определить кодовый блок, который будет выполняться после выхода из блока try/catch. В частности, исключительная ситуация может возникнуть в связи с ошибкой, приводящей к преждевременному возврату из текущего метода. Но в этом методе мог быть открыт файл, который нужно закрыть, или же установлено сетевое соединение, требующее разрывания. Подобные ситуации нередки в программировании, и поэтому для их разрешения в C# предусмотрен удобный способ: воспользоваться блоком finally.

Использование блока finally гарантирует, что некоторый набор операторов будет выполняться всегда, независимо от того, возникло исключение (любого типа) или нет.

Для того чтобы указать кодовый блок, который должен выполняться после блока try/catch, достаточно вставить блок finally в конце последовательности операторов try/catch. Ниже приведена общая форма совместного использования блоков try/catch и finally:

Блок finally будет выполняться всякий раз, когда происходит выход из блока try/catch, независимо от причин, которые к этому привели. Это означает, что если блок try завершается нормально или по причине исключения, то последним выполняется код, определяемый в блоке finally. Блок finally выполняется и в том случае, если любой код в блоке try или в связанных с ним блоках catch приводит к возврату из метода.

Давайте рассмотрим пример:

Блок finally

C точки зрения синтаксиса блок finally следует после блока try, и формально блоки catch для этого не требуются. Следовательно, блок finally можно ввести непосредственно после блока try, опустив блоки catch. В этом случае блок finally начнет выполняться сразу же после выхода из блока try, но исключения обрабатываться не будут.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *