Создание специальных исключений 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Создание специальных исключений



 

Хотя для уведомления о возникновении ошибки во время выполнения можно всегда генерировать экземпляры System.Exception, иногда гораздо выгоднее создавать строго типизированное исключение, способное предоставлять уникальные детали по текущей проблеме. Например, предположим, что понадобилось создать специальное исключение. Для получения любого специального исключения в первую очередь необходимо создать новый класс, унаследованный от класса System.Exception или System.ApplicationException (по соглашению, имена всех классов исключений оканчиваются суффиксом Exception; в действительности это является рекомендуемым практическим приемом в.NET).

Если планируется создать действительно заслуживающий внимания специальный класс исключения, необходимо позаботиться о том, чтобы он соответствовал наилучшим рекомендациям.NET. В частности это означает, что он должен:

  • наследоваться от ApplicationException;
  • сопровождаться атрибутом [System.Serializable];
  • иметь конструктор по умолчанию;
  • иметь конструктор, который устанавливает значение унаследованного свойства Message;
  • иметь конструктор для обработки «внутренних исключений»;
  • иметь конструктор для обработки сериализации типа.

 

Рассмотрим пример:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections;

 

namespace LC_Console

{

// Специальное исключение

[Serializable]

public class MyException: ApplicationException

{

public MyException() { }

public MyException(string message): base(message) { }

public MyException(string message, Exception ex): base(message) { }

// Конструктор для обработки сериализации типа

protected MyException(System.Runtime.Serialization.SerializationInfo info,

System.Runtime.Serialization.StreamingContext contex)

: base(info, contex) { }

}

 

class Program

{

static int MyDel(int x, int y)

{

 

if (y == 0)

{

MyException exc = new MyException("Ошибка: деление на \"0\" зафиксировано");

exc.HelpLink = "Подробности на сайте: http:\\www.microsoft.com";

throw exc;

}

return x / y;

}

 

static void Main()

{

 

try

{

MyDel(5, 0);

}

// Обрабатываем общее исключение

catch (MyException ex)

{

Console.WriteLine("Обнаружена ошибка!\n");

Console.WriteLine(ex.Message);

Console.WriteLine(ex.HelpLink);

}

Console.WriteLine("\nДля продолжения нажмите любую клавишу...");

Console.ReadKey();

}

}

}

 

Рис. 3. 1. Результат работы кода выше

 

Как видим, в данном примере создается специальный класс исключения MyException, включающий в себя все вышеуказанные рекомендации.

Обработка многочисленных исключений

Обработка многочисленных исключений

 

Применение нескольких операторов catch

 

С одним оператором try можно связать несколько операторов catch. И на практике это делается довольно часто. Но все операторы catch должны перехватывать исключения разного типа:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections;

 

namespace LC_Console

{

class Program

{

static void Main()

{

 

try

{

Console.Write("Введите число типа Byte: ");

byte b = byte.Parse(Console.ReadLine());

int[] myArr = new int[5] { 1, 2, 0, 10, 12 };

Console.WriteLine("Исходный массив: ");

for (int j = 0; j <= myArr.Length; j++)

Console.WriteLine("{0}\t", myArr[j]);

int i = 120;

Console.WriteLine("\nДелим на число: \n");

foreach (int d in myArr)

Console.WriteLine(i / d);

}

// Обрабатываем исключение, возникающее

// при арифметическом переполнении

catch (OverflowException)

{

Console.Write("Данное число не входит в диапазон 0 - 255.");

}

// Исключение при делении на 0

catch (DivideByZeroException)

{

Console.WriteLine("Делить на ноль нельзя.");

}

// Исключение при переполнении массива

catch (IndexOutOfRangeException)

{

Console.WriteLine("Индекс выходит за пределы.");

}

Console.WriteLine("\nДля продолжения нажмите любую клавишу...");

Console.ReadKey();

}

}

}

 

Рис. 1. 1. Результат работы кода выше

 

Как следует из приведенного выше результата, каждый оператор catch реагирует только на свой тип исключения.

Вообще говоря, операторы catch выполняются по порядку их следования в программе. Но при этом выполняется только один блок catch, в котором тип исключения совпадает с типом генерируемого исключения. А все остальные блоки catch пропускаются.

Перехват всех исключений

 

Время от времени возникает потребность в перехвате всех исключений независимо от их типа. Для этой цели служит оператор catch, в котором тип и переменная исключения не указываются. Ниже приведена общая форма такого оператора:

 

catch

{

// Обработка исключений

}

 

С помощью такой формы создается «универсальный» обработчик всех исключений, перехватываемых в программе. Давайте модифицируем предыдущий пример и добавим вместо трёх операторов catch, следующий код:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections;

 

namespace LC_Console

{

class Program

{

static void Main()

{

try

{

Console.Write("Введите число типа byte: ");

byte b = byte.Parse(Console.ReadLine());

int[] myArr = new int[5] { 1, 2, 0, 10, 12 };

Console.WriteLine("Исходный массив: ");

for (int j = 0; j <= myArr.Length; j++)

Console.WriteLine("{0}\t", myArr[j]);

int i = 120;

Console.WriteLine("\nДелим на число: \n");

foreach (int d in myArr)

Console.WriteLine(i / d);

}

// Обрабатываем все исключения

catch {

Console.WriteLine("Возникла непредвиденная ошибка.");

}

Console.WriteLine("Для продолжения нажмите любую клавишу...");

Console.ReadKey();

}

}

}

 

Рис. 2. 1. Результат работы кода выше

 

В подавляющем большинстве случаев «универсальный» обработчик исключений не применяется. Как правило, исключения, которые могут быть сгенерированы в коде, обрабатываются по отдельности. Неправильное использование «универсального» обработчика может привести к тому, что ошибки, перехватывавшиеся при тестировании программы, маскируются. Кроме того, организовать надлежащую обработку всех исключительных ситуаций в одном обработчике не так-то просто. Иными словами, «универсальный» обработчик исключений может оказаться пригодным лишь в особых случаях, например в инструментальном средстве анализа кода во время выполнения.

 

Вложение блоков try

 

Один блок try может быть вложен в другой. Исключение, генерируемое во внутреннем блоке try и не перехваченное в соответствующем блоке catch, передается во внешний блок try:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections;

 

namespace LC_Console

{

class Program

{

static void Main()

{

Console.Write("Введите длину массива: ");

 

try

{

int i = int.Parse(Console.ReadLine());

int[] myArr = new int[i];

Console.WriteLine("\nВведите элементы массива: ");

for (int j = 0; j < i; j++)

{

Console.Write("{0}й элемент: ", j + 1);

// Вложенный оператор try

try

{

myArr[j] = int.Parse(Console.ReadLine());

}

catch (OverflowException)

{

Console.WriteLine("\nОшибка: Слишком большое число.\n");

}

}

 

}

catch (FormatException ex)

{

Console.WriteLine("\nОшибка: " + ex.Message);

}

Console.WriteLine("\nДля продолжения нажмите любую клавишу...");

Console.ReadKey();

}

}

}

 

Рис. 4. 1. Результат работы кода выше

 

Обратим внимание, что во вложенном операторе try не определяется исключение для нарушения формата ввода элементов массива, но при этом, данное исключение перехватывается внешним блоком try. Стоит отметить, что количество вложенных операторов try не ограничено.

 



Поделиться:


Последнее изменение этой страницы: 2016-08-15; просмотров: 283; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.15.225.173 (0.029 с.)