Код, що не викликає винятків у Visual C # (Sharp)

Тепер, коли ми знаємо, як реалізовувати обробники винятків, розглянемо ще кращий підхід до проблеми винятків: не викликати їх Ми будемо фокусіраться на те, як можна зробити код більш безпечним і менш схильним до генірованію винятків

На жаль занадто часто виключення, такі як NuliReferenceException, воікают тому, що розробники не вживають заходів, щоб упевнитися в дійсності стану у фрагменті коду А недійсне стан викличе виняток Більше того, один з прикладів у цій главі містить саме таку ситуацію, яку ви, напевно, помітили Ось цей код з його маленьким дурним упущенням, яке може вилитися в виняток:

void TestCallingExample() { CallingExample els = null try {

els – new CallingExample() elsMethod()

}

catch (Exception) { }

ConsoleWriteLine(&quotDepth is (&quot + clsGetDepthO + n)&quot)

}

Проблемну ділянку коду виділений жирним шрифтом, а проблема полягає в тому, що в ньому робиться припущення, що змінна els буде завжди звертатися до дійсного екземпляру CallingExample Дане припущення відноситься до класу припущень, які ми не можемо дозволити собі допускати Якщо виняток відбудеться при створенні екземпляра CallingExample, то значення пеменной els залишиться null, а блок catch перехопить це виняток, таким оазом, запобігаючи зависання програми Але використання методу clsGetDepthO відразу ж після цього зводить всю нашу захист нанівець, т к перенісши els містить null, що викличе виключення NuliReferenceException Краще написати цей код так:

void TestCallingExample() { CallingExample els = null try {

els = new CallingExample() elsMethod()

}

catch (Exception) { }

if (els = null) {

ConsoleWriteLine(&quotDepth is (&quot + elsGetDepth() + &quot)&quot)

}

}

У рядку, виділеної жирним шрифтом, ілюструється захисний код, який перевіряє, чи не містить змінна cis значення null, і якщо не містить, то дозволяє звернення до методу cisGetDepthO Написання коду таким чином робить його захищеним від винятків Це не означає, що виключення не можуть виникнути зовсім, тому що вони можуть відбутися в методі GetDeptho, але по ставлюся до методу TestCaliingExample () Ми убезпечилися, наскільки могли, і преолагаем малу ймовірність виникнення виключень в методі GetDepth ()

Але в методі TestCaliingExample () відсутній спосіб індикації, чи була обротка успішною Код, що викликає метод TestCaliingExample (), припускає, що в результаті цього виклику завжди буде щось зроблено Окрім як возникнове виключення в викликається методі, викликає код не має ніякої воожності дізнатися, якщо щось в методі TestCaliingExample () не спрацювало

Код, який повідомляє про проблеми з допомогою винятку, є одновренно і добром, і злом Добром тому, що код повідомляє про виниклу проблему Злом тому, що іноді ви знаєте, що може виникнути якась некрітічкая помилка, і ви не хочете, щоб це виняток піднімалося наверх ієрархії виконання програми У таких випадках виняток необхідно перехопити, що викликає ускладнення коду

Скажімо, необхідно перетворити строкове представлення числа власне в число Надані NET процедури перетворення зазвичай видають рультат у разі успішного виконання операції, але генерують виняток, еи щось іде не так І тільки виключення, а не повертається значення або паретр Але при перетворенні чисел ми знаємо, що з такими операціями завжди існує можливість будь-якої помилки, тому для такого випадку нам неоодімо надати обробник виключення Розглянемо наступний код для перетворення числа:

int TestGetValue(string buffer) { int retval = 0

try {

retval = intParse(buffer)

}

catch (FormatException ex) { ConsoleWriteLine(&quotException (&quot + exMessage + &quot)&quot)

}

return retval

}

У даному прикладі код усвідомлює, що якщо в викликаному методі Parse () рядок параметр buffer неправильного формату, наприклад, містить неприпустимі

символи, то буде згенеровано виняток Виняток буде перехоплено, оаботано (проблема встановлена ​​за допомогою властивості Message виключення), після чого значення змінної retval буде повернуто зухвалому коду Але як виняток вплине на результати виконання подальшого коду Ми бачимо, що повертається методом parsed мінлива retval була инициализирована значенням за замовчуванням 0 Це дійсне число і може бути інтерпретовано як результат успішної перетворення

Ця обставина ставить розробника у скрутне становище 11ерехватая виняток, метод TestGetvaiueo як би говорить: Я завжди поверну визающему коду дійсне значення. Тим не менш, деякі нібито действельние повертаються значення на ділі не є такими Це значення, які повертаються, коли при перетворенні числа виникає виняток Таким обром, перехоплюючи виняток, ми чинимо зовсім неправильно, т к тут потрібно надати задачу перехоплення виключення зухвалому коду вищого рівня Але й тут не все так просто Чи дійсно ми хочемо сповіщати викликає код, що виконання перетворення є неможливим Можливо, викликає код більш зацікавлений в тому, чи дійсно повернене значення У такому випадку сповіщення його про внутрішні проблемах методу буде те саме що докладанні генеральному директору про те, що в офісі закінчилися дужки для степлерів Кечно ж, у відповідному контексті дужки для степлерів також важливі, і без них продуктивність компанії може знизитися на соту частку відсотка, але чи дійсно ми будемо доповідати про цю проблему генеральному директору

Проблема з перетворенням відома розробникам Microsoft, і для її вирішення вони застосовують підхід, який може стати в нагоді і нам Як ми дізналися в розділі 3, строкове представлення число можна перетворити у власне число з помью двох методів:

• метод Parse () повертає дійсне число, якщо їй передається действельное строкове представлення числа в іншому випадку цей метод видає виключення

П метод TryParse (), крім перетвореного значення у разі успішного прбразованія, також повертає значення true або false, яке вказує на рультат перетворення

Метод TestGetvalue <) можна модифікувати для використання в ньому методу

TryParse () таким чином:

bool TestGetvalue(string buffer, out int val) { bool retval = false

if (intTryParse(buffer, out val)) { retval = true

}

return retval

}

У модифікованому прикладі метод TestGetvalue () повертає true або false, таким чином вказуючи успіх чи невдачу операції перетворення рядка в число Якщо повертається true, параметр val буде вказувати на допустиму кількість в іншому випадку цей параметр не використовується

Деякі з читачів могли помітити, що спосіб застосування методів Parse () і TryParse () не блищить винахідливістю А саме метод TestGetvalue () можна звести до одного оператора:

bool TestGetvalue(string buffer, out int val) { return intTryParse(buffer, out val)

}

Джерело: Гросс К С # 2008: Пер з англ – СПб: БХВ-Петербург, 2009 – 576 е: ил – (Самовчитель)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*