Хвърляне на изключения

Както бе споменато по-горе, методът ProcessFile просто предава изключението на процедурата Sub Main, от която е извикан. В процедурата Sub Mai n командата за повикване също е затворена в блок Try-Catch, така че изключението ще бъде обработено. От друга страна, подобно решение изглежда малко наивно и ако класовете, които пишете, се използват от други програмисти, то става просто опасно. Но дори и нещата да се получат по някакъв начин, потребителите на вашия код едва ли ще бъдат доволни от факта, че безразборно хвърляте изключения, без да се опитвате да се справите с тях.

Най-добре е да опитате и да почистите след себе си, ако е възможно, и след това да използвате ключовата дума Throw, за да предадете обекта за изключение на повикващия. В глава 4 се споменава, че VB .NET не поддържа детерминирано завършване. Следователно, ако сте създали обект с D1 спосе метод, този метод трябва да бъде извикан преди да се хвърли изключение. Същото се отнася и за отваряне на файлове и получаване на графичен контекст. Следният фрагмент показва условната структура на такъв код:

'Създайте локален обект с метод Dispose

„Код. което може да хвърли изключения

Catch (e Като изключение)

Ако обаче наистина искате да програмирате „както се очаква“, не се ограничавайте само с рестартиране на изключението. Опитайте се да запазите кода си възможно най-описателен и да включите допълнителна информация в обекта за изключение. Има три възможности за това.

  1. Добавете смислено съобщение към изключението и го инициирайте отново. Може би новата информация ще бъде полезна.
  2. Изхвърлете изключение от един от стандартните типове, получени от типа на текущото изключение, за да опишете по-добре ситуацията.
  3. Създайте нов клас на изключение, получен от типа на текущото изключение, който ще опише ситуацията по-добре от всеки от стандартните класове.

Решенията се класират във възходящ ред на приоритет и в идеалния случай винаги трябва да използвате точка 3. На практика програмистите се ръководят от преценката си каква информация за изключението трябва да бъде предадена за по-нататъшна обработка.

Например, представете си следната ситуация: двойки ключ/стойност се четат от източника на данни и не е намерена двойка стойност за последния ключ. Програмата приема, че дадена стойност е свързана с всеки ключ, така че при опит за четене възниква неочаквано I/O изключение (четенето на данни от файл е описано в Глава 9).

Сега искате да съобщите за случващото се на обаждащия се. За да добавите ред към изключение, можете да използвате специална версия на конструктора на клас Exception:

Public Sub New (съобщение от ByVal като низ)

Следващият фрагмент добавя нов ред към обекта IOException, заявявайки, че няма стойност за последния ключ, и след това повдига изключението.

Dim excep As New IQException ("Липсваща стойност за последния ключ") Хвърли excep

След като получи хвърлено изключение, външният код получава текста на съобщението, използвайки метода Message на класа Exception и научава за проблема.

На практика в ситуации като тази е по-често да се хвърля IOException-извлечено EndOfStream-Exception. Операциите на потока от данни са обхванати в глава 9.

Втората ситуация се реализира по елементарен начин поради основното правило за наследяване: производен клас винаги може да се използва вместо основен клас. Просто трябва да създадете изключение от производния клас, който е по-подходящ за тази ситуация.

Последният случай изисква допълнителна работа, тъй като изисква дефиниране на клас, който произлиза от съществуващ клас на изключение. Да предположим, че искате да дефинирате нов клас на изключение, който произлиза от System. 10. lOException. Новият клас се различава от стария само в едно свойство ReadOnly, което връща ключ, с който не е свързана стойност на двойка:

Публичен клас LastValueLostException наследява System.I0.I0.Exception

Частен mKey As String

Public Sub New (ByVal theKey As String)

MyBase.New ("Не е намерена стойност за последния ключ")

Публична собственост само за четене LastKey () Като низ Вземете

Този ред извиква конструктора на базовия клас (и в крайна сметка конструктор на предшественик на изключение).

Може би сте забелязали, че класът LastValueLostException не замества други методи, като метода ToString, наследен от изключение. В стандартни ситуации обектите за изключение винаги трябва да извеждат стандартни съобщения.

Как да използвам създадения клас в програмата? Например, ако последният ключ без двойка стойности е „упс“, следната команда ще предизвика изключение:

Хвърляне на New LastValueLostException ("ами сега")

Обърнете внимание, че класът IOException, както и много стандартни изключения, е получен от Exception, а не от ApplicationException.

Изпълнителната среда ви помага да направите следващата стъпка. Йерархията на изключенията се разделя на два клона, както е показано на фиг. 7.1.

Фигура: 7.1. Двата основни клона на йерархията на изключенията

Класовете Exceptlon, AppllcationExcepti on и SystemExcepti на класовете имат същата функционалност. Съществуването на три класа вместо един не е нищо повече от удобна абстракция, която улеснява разбирането на изключенията, хвърлени във вашите програми.

Изключения като заместител на goto

Обработката на изключения, комбинирана с дефиниране на вашите собствени класове изключения, елиминира необходимостта от GoTo. Например, глава 3 даде пример за оправдано използване на GoTo за прекъсване на вложени цикли, когато възникне грешка във вътрешния цикъл. Програмист на VB .NET в ситуация като тази просто обвива целия цикъл в блок Try-Catch, както е показано по-долу:

Затъмнете getData като низ

Dim i, j като цяло число

Dim e As System.I0.I0Exception

За j = 1 до 100 Console.WriteC'Впишете данните, натиснете клавиша Enter между "& _

"ZZZ до края:") getData _

Console.ReadLine () Ако getData = "ZZZ" Тогава

e Нова System.I0.I0Exception ("Въвеждането на данни приключи" & _

"по желание на потребителя") Хвърли друго

В горния фрагмент избраните редове не могат да бъдат обединени със следната конструкция:

Dim e As New System.IO.IOException („Въвеждането на данни приключи при поискване от потребителя“)

Поради правилата за видимост на VB .NET обектът за изключение няма да бъде наличен в раздела за улавяне.

Когато се използват блокове Try-Catch, често има код, който трябва да бъде изпълнен както при нормално завършване, така и при изключение. Например и в двата случая трябва да затворите файлове, да извикате методи за изхвърляне и т. Н. Дори в простия пример в началото на главата, командата ReadLine е била необходима, за да държи прозореца на конзолата на екрана, докато не се натисне клавишът Enter .

За да може дадено парче да се изпълни, независимо дали в програмата е хвърлено изключение или не, в блока Try-Catch е включен раздел Накрая, който е показан с получер шрифт в следния пример:

Затъмнете аргументите (). аргумент Като низ

args = Околна среда. GetCommandLineArgs ()

Console.WriteLine ("Натиснете enter за край")

И накрая, кодът в раздела Накрая се изпълнява преди предаване на изключения на външен код и преди връщане от функцията. .

Препоръки за използване на изключения

Изключенията изглеждат зрелищни и начинаещите често са склонни да ги прекаляват. Наистина, струва ли си време за разбор на въведеното от потребителя, когато можете просто да хвърлите изключение? Не се изкушавайте. Ако се използва неправилно, обработката на изключения значително забавя програмата. Следват някои насоки за използване на изключения в програма.

  1. Изключение е признак за извънредна ситуация; не използвайте изключения за просто предаване на информация (видяхме програма, в която при успешно завършване на функцията беше хвърлено изключение SUCCESS_EXCEPTION).
  2. Не заменяйте тривиалните проверки с обработка на изключения. Например, изключения не трябва да се използват за проверка за достигане до края на файла (EOF).
  3. Избягвайте фрагментирано обработване на изключения, при което почти всяка команда е обвита в отделен блок Try-Catch. Опаковането на цялата операция в един блок Try-Catch обикновено е за предпочитане пред използването на множество блокове.
  4. Не поглъщайте изключения с Catch e As Excepti на конструкции с празен инструкционен блок, освен ако няма достатъчно основателна причина за това. Тази конструкция е еквивалентна на безмисленото използване на On Error Resume в стари програми на VB и не е желателно да се използва по същите причини. Ако възникне изключение в програмата, обработете го или го предайте за по-нататъшна обработка.
  5. Последната препоръка по-скоро може да се нарече „правило за добра форма“. Когато предавате изключението на външен код за по-нататъшна обработка, добавете нова информация към него (или дефинирайте нов клас на изключение), така че външният код да може да определи точно какво се е случило и какви мерки са предприети за коригиране на ситуацията.