Кратко съдържание


Конструкцията try–finally



страница38/73
Дата21.07.2018
Размер9.03 Mb.
#76887
1   ...   34   35   36   37   38   39   40   41   ...   73

Конструкцията try–finally


Когато възникне изключение, изпълнението на програмата спира и управ­лението се предава на най-близкия блок за обработка на изключения. Това означава, че кодът който е между фрагмента, породил изключението и началото на блока за обработка на изключението няма да се изпълни. Да разгледаме следния фрагмент:

StreamReader reader = File.OpenText("example.txt");

string fileContents = reader.ReadToEnd();

reader.Close();


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

Къде е проблемът?


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

Решението


Проблемът може да бъде решен чрез програмната конструкция try-finally в C#:

try

{

// Do some work that can raise an exception



}

finally


{

// This block will always execute

}


Тя осигурява гарантирано изпълнение на зададен програмен блок неза­ви­симо дали в блока преди него възникне изключение или не. Конструк­цията има следното поведение:

  • Ако в try блока не възникне изключение, след завършва­нето на изпълнението му, се изпълнява веднага след него и finally блокът.

  • Ако в try блока възникне изключение, изпъл­нението на try блока ще се прекъсне и CLR ще започне да търси обработчик за възникналото изключение. В този случай има две възможности:

    • CLR намира обработчик за изключението. Тогава първо ще се изпълни finally блокът и едва след това намереният от CLR обработчик.

    • CLR не намира подходящ обработчик. Тогава първо CLR ще обработи изключението (ще даде някакво съобщение за грешка) и след това ще изпълни finally блока.

Може да изглежда сложно, но всъщност не е. Важното нещо, което трябва да запомним е, че finally блокът се изпълнява винаги, независимо от това какво се е случило в try блока. Останалите детайли не са чак толкова важни.

Конструкцията try-catch-finally


Конструкцията try-finally може да се комбинира с конструкцията try-catch. Така се получава try-catch-finally конструкцията, която работи по следния начин:

  • Ако в try блока не възникне изключение, се изпълняват после­дователно try и finally блоковете.

  • Ако в try блока възникне изключение, което може да се улови от catch филтрите на try-catch-finally конструкцията, първо се изпълнява съответният catch блок, а след него се изпълнява и finally блокът.

  • Ако в try блока възникне изключение, което не отговаря на catch филтрите от try-catch-finally конструкцията, CLR търси подходящ catch филтър в стека за изпълнение на програмата за да обработи изключението. Отново има две възможности:

    • CLR намира обработчик за изключението. Тогава първо ще се изпълни finally блокът и едва след това намереният от CLR обработчик.

    • CLR не намира подходящ обработчик. Тогава първо CLR ще обработи изключението (ще даде някакво съобщение за грешка) и след това ще изпълни finally блока.

За повече яснота да разгледаме един пример:

try

{

int a = 0;



int b = 1/a;

}

catch (ArithmeticException)



{

Console.WriteLine("ArithmeticException caught.");

}

finally


{

Console.WriteLine("Finally block executed.");

}


В примера в try блока възниква аритметично изключение заради делението на 0, то се обработ­ва веднага от catch блока и накрая се изпълнява finally блокът. При изпълнението на примера се получава следният резултат:

Нека сега разгледаме пример, в който възниква изключение, което не се прихваща никъде в програмата:



try

{

int a = 0;



int b = 1/a;

}

finally



{

Console.WriteLine("Finally block executed.");

}


В случая CLR вътрешно ще прихване изключението, ще отпечата съобще­ние за грешка и едва след това ще изпълни finally блока:

Да разгледаме и още един пример:



try

{

try



{

int a = 0;

int b = 1/a;

}

finally



{

Console.WriteLine("Finally block executed.");

}

}

catch (ArithmeticException)



{

Console.WriteLine("ArithmeticException caught.");

}


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


try-finally за освобождаване на ресурси


В блока, който се изпълнява задължително (finally блока), може да се съдържа код за освобождаване на ресурси, който трябва да се изпълни винаги. Така се осигурява почистване след всяка успешно започната операция, преди да се върне управлението на извикващия блок или да продължи да се изпълнява кодът след finally блока. Ето един пример:

///

/// Returns the # of first line from the given text file

/// that contains given pattern or -1 if such line is not found

///

static int FindInTextFile(string aPattern, string aFileName)

{

int lineNumber = 0;



StreamReader inF = File.OpenText(aFileName);

try


{

while (true)

{

string line = inF.ReadLine();



if (line == null)

break; // end of file reached

lineNumber++;

if (line.IndexOf(aPattern) != -1)

return lineNumber;

}

return -1;



}

finally


{

inF.Close(); // The file will never remain opened

}

}


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

Ако не възникне изключение по време на търсенето, след изпълнението на return оператора, ще бъде изпълнен finally блокът.

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

Ако при търсенето възникне изключение, но то не бъде прихванато, то ще се обработи от CLR и finally блокът ще бъде изпълнен едва след това. Методът няма да върне стойност и програмата ще приключи аварийно.





Сподели с приятели:
1   ...   34   35   36   37   38   39   40   41   ...   73




©obuch.info 2024
отнасят до администрацията

    Начална страница