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



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

Свойства на изключенията


Изключенията в .NET Framework са обекти. Класът System.Exception е базов клас за всички изключения в CLR. Той дефинира свойства, общи за всички .NET изключения, които съдържат информация за настъпилата грешка или необичайна ситуация.

Ето и някои често използвани свойства:



  • Messageтекстово описание на грешката.

  • StackTraceтекстова визуализация на състоянието на стека в момента на възникване на изключението. Дава информация за това в кой метод в кой файл и на кой ред във файла е възникнало изключението. Имената на файловете и редовете са налични само при компилиране в дебъг режим.

  • InnerExceptionизключение, което е причина за възникване на текущото изключение (ако има такова). Например имаме метод който чете от файл и после форматира прочетените данни. Ако по време на четенето възникне изключение то може да бъде прихванато и да се хвърли ново изключение от друг, собствено дефиниран тип, като прихванатото изключение се присвои на свойството InnerException. Целта е обработчикът на изключението да получи информация както за възникналия проблем, така и за неговия първопричинител. Чрез свойството InnerException изключенията могат да се свързват във верига, която съдържа последователно всички изключения, които са причинили изключението в нейното начало.

Ще илюстрираме употребата на свойствата с един пример:

using System;
class ExceptionsTest

{

public static void CauseFormatException()



{

string s = "an invalid number";

Int32.Parse(s);

}
static void Main(string[] args)

{

try


{

CauseFormatException();

}

catch (FormatException fe)



{

Console.Error.WriteLine(

"Exception caught: {0}\n{1}",

fe.Message, fe.StackTrace);

}

}

}



Свойството StackTrace е изключително полезно при идентифициране на причината за изключението. Резултатът от примера е информация за прихванатото в Main() метода изключение, отпечатана върху стандартния изход за грешки:

Exception caught: Input string was not in a correct format.

at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)

at System.Int32.Parse(String s)

at ExceptionsTest.CauseFormatException() in c:\consoleapplication1\exceptionstest.cs:line 8

at ExceptionsTest.Main(String[] args) in c:\consoleapplication1\exceptionstest.cs:line 15


Имената на файловете и номерата на редовете са достъпни само ако сме компилирали с дебъг информация. Ако компилираме по-горния пример в Release режим, ще получим много по-бедна информация от свойството StackTrace:

Exception caught: Input string was not in a correct format.

at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)

at ExceptionsTest.Main(String[] args)


Превключването между Debug и Release на компилация става много лесно от лентата с инструменти за компилация във VS.NET:


Йерархия на изключенията


Изключе­нията са класове и като такива могат да се наследяват и да образуват йерархии. Както вече знаем, всички изключения в .NET Framework наследяват класа System.Exception. Този клас има няколко важни наследника, от които обектната йерархия продължава в няколко посоки. Това се вижда от следната диаграма:

Някои изключения директно наследяват System.Exception, например кла­совете System.SystemException и System.ApplicationException.

Системните изключения, които се използват от стандартните библиотеки на .NET и вътрешно от CLR, наследяват класа System.SystemException. Ето някои от тях:


  • System.ArithmeticException – грешка при изпълнението на аритме­тична операция, например деление на 0, препълване на целочислен тип и др.

  • System.ArgumentException – невалиден аргумент при извикване на метод.

  • System.NullReferenceException – опит за достъп до обект, който има стойност null.

  • System.OutOfMemoryException – паметта е свършила.

  • System.StackOverflowException – препълване на стека. Обикновено възниква при настъпване на безкрайна рекурсия.

  • System.IndexOutOfRangeException – опит за излизане от границите на масив.

Изключенията дефинирани от потребителя трябва да наследяват класа System.ApplicationException. Така потребителските програми ще пре­дизвикват изключения само от този тип или негови наследници. Това дава възможност да се разбере дали проблемът е на ниво потребителски код или е свързан със системна грешка. Възможно е потребителски-дефини­рано изключение да наследи и директно System.Exception, а не System. ApplicationException, но има много спорове дали това е добра практика. Някои експерти твърдят, че наследяването на ApplicationException ус­ложнява излишно йерархията, докато други смятат, че е по-важно да се разграничават системните от потребителските изключения.

Подредбата на catch блоковете


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

try

{

// Do some works that can raise an exception



}

catch (System.ArithmeticException)

{

// Handle the caught arithmetic exception



}

прихваща освен ArithmeticException и изключенията OverflowException и DivideByZeroException. В този пример всичко е наред, но нека разгледаме следния код:

static void Main()

{

string s = Console.ReadLine();



try

{

Int32.Parse(s);



}

catch (Exception) // Трябва да е най-накрая

{

Console.WriteLine("Can not parse the number!");



}

catch (FormatException) // Този код е недостижим

{

Console.WriteLine("Invalid integer number!");



}

catch (OverflowException) // Този код е недостижим

{

Console.WriteLine("The number is too big!");



}

}


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



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

Изключения и неуправляван код


Управлявания .NET код може да предизвика само изключения, наследници на System.Exception. Неуправляваният код може да предизвика и други изключения. За прихващане на всички изключения в C# се използва следната конструкция:

try

{

// Do some work that can raise an exception



}

catch


{

// Handle the caught exception

}


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




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




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

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