Оброка виняткових ситуацій C#

Доброї пори часу. Сьогодні я вам розповім як і для чого потрібно використовувати перехоплення в винятковій ситуацій, та де особливо важливо це виконувати.

При використанні небезпечних операцій (з’єднання з базою даних, читання файлу з диску або з іншого джерела даних) може виникнути певна виняткова ситуація – Exception (втрата мережевого підключення, неможливість здійснити певну операцію над файлом через його зайнятість і т.д.). При виникненні необроблених  ситуацій програма як правило припинить свою роботу, але наприклад якщо помилка не критична то як зробити щоб програма виконувала певні дії (логування, усунення неполадки, повідомляла користувача, звільняла зайняті ресурси) та продовжувала свою функціональність?

Відповідь на це питання проста – exception handling.

Всі класи виняткових ситуацій унаслідуються від базового класу System.Exception. Наприклад клас FileNotFoundException унаслідується від класу IOException, який в свою чергу унаслідується від класу Exception. В конструкції C# для обробки виняткових ситуацій існують такі блоки як try, catch, finally.

Блок try..catch

Для того щоб обробити виняткову ситуацію можна використовувати ці два блоки, продемонструю на прикладі:

private static Byte[] ReadFile(String path)
{
    FileStream fs = new FileStream(path, FileMode.Open);
    Byte[] result = new Byte[fs.Length];
    Int32 readCount = 0;
    while (readCount != fs.Length)
    {
        readCount+= fs.Read(result, readCount, (Int32)fs.Length);
    }
    return result;
}

В цьому прикладі в нас виконується небезпечна операція зчитування байтів з файлу. А що буде якщо файл відсутній або зайнятий іншим процесом? Правильно виникне виняткова ситуація:

1

2

Для того щоб це усунути потрібно застосувати блоки try..catch:

private static Byte[] ReadFile(String path)
{
     Byte[] result;
     FileStream fs;
     try
     {
          fs = new FileStream(path, FileMode.Open);
          result = new Byte[fs.Length];
          Int32 readCount = 0;
          while (readCount != fs.Length)
          {
               readCount += fs.Read(result, readCount, (Int32)fs.Length);
          }
          return result;
     }
     catch (FileNotFoundException)
     {
         MessageBox.Show("File was not found");
         return null;
     }
     catch(IOException ex)
     {
         throw ex;
     }
}

В цьому коді я перехопив виняткову ситуацію та обробив її необхідним чином. Для коректної обробки виняткових ситуацій спочатку потрібно ставити блоки catch з перехопленням ексцепшенів, які знаходяться нижче по ієрархії. Тобто якщо ви спочатку обробите Exception, а потім інший ексцепшен який від нього унаслідується, то другий під обробку не попаде, так як він є нижчим по ієрархії наслідування.

Отже висновок: завжди обробляйте виняткові ситуації починаючи з наймолодшого (найнижчого в ієрархії наслідування).

Як ви бачите в першому блоці catch обробляю ексцепшен FileNotFoundException та в другому IOException. При обробці першої виняткової ситуації (FileNotFoundException) я просто повідомляю користувача, а при виникненні наступної (IOException ex) я передаю це повідомлення верх по стеку виклику, тобто користувачу, який буде викликати мій метод ReadFile.

Блок finally

В нашому методі ReadFile ще не вистачає одного виклику, для звільнення зайнятих ресурсів. Це має бути виклик метод FileStream.Close(). Для коректного виклику таких методів існує блок finally, який буде запускатись в будь-якому випадку, навіть коли виняткова ситуація не виникла. В ньому ми і розмістимо наш виклик методу для звільнення файлу:

private static Byte[] ReadFile(String path)
{
     Byte[] result;
     FileStream fs = null;
     try
     {
          fs = new FileStream(path, FileMode.Open);
          result = new Byte[fs.Length];
          Int32 readCount = 0;
          while (readCount != fs.Length)
          {
               readCount += fs.Read(result, readCount, (Int32)fs.Length);
          }
          return result;
     }
     catch (FileNotFoundException)
     {
          MessageBox.Show("File was not found");
          return null;
     }
     catch (IOException ex)
     {
          throw ex;
     }
     finally
     {
          if(fs != null)
          fs.Close();
     }
}

В цей блок ми можемо добавить будь-які потрібні нам дії.

Ну і на кінець я покажу всі поля базового класу виняткових ситуацій Exception.

3

Детальнішу інформацію ви зможете знайти на сайті Microsoft MSDN. Дякую за увагу Smile

Advertisements

, , , , ,

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: