Книга: C# 4.0: полное руководство

Подробное рассмотрение класса Exception

Подробное рассмотрение класса Exception

В приведенных выше примерах исключения только перехватывались, но никакой существенной обработке они не подвергались. Как пояснялось выше, в операторе catch допускается указывать тип и переменную исключения. Переменная получает ссылку на объект исключения. Во всех исключениях поддерживаются члены, определенные в классе Exception, поскольку все исключения являются производными от этого класса. В этом разделе будет рассмотрен ряд наиболее полезных членов и конструкторов класса Exception и приведены конкретные примеры использования переменной исключения.

В классе Exception определяется ряд свойств. К числу самых интересных относятся три свойства: Message, StackTrace и Targetsite. Все эти свойства доступны только для чтения. Свойство Message содержит символьную строку, описывающую характер ошибки; свойство StackTrace — строку с вызовами стека, приведшими к исключительной ситуации, а свойство ТагgetSite получает объект, обозначающий метод, сгенерировавший исключение.

Кроме того, в классе Exception определяется ряд методов. Чаще всего приходится пользоваться методом ToString(), возвращающим символьную строку с описанием исключения. Этот метод автоматически вызывается, например, при отображении исключения с помощью метода WriteLine().

Применение всех трех упомянутых выше свойств и метода из класса Exception демонстрируется в приведенном ниже примере программы.

// Использовать члены класса Exception.
using System;
class ExcTest {
  public static void GenException() {
    int[] nums = new int [4];
    Console.WriteLine("До генерирования исключения.");
    // Сгенерировать исключение в связи
    //с выходом за границы массива,
    for(int i=0; i < 10; i++) {
      nums[i] = i;
      Console.WriteLine("nums[{0}]: {1}", i, nums[i]);
    }
    Console.WriteLine("He подлежит выводу");
  }
}
class UseExcept {
  static void Main() {
    try {
      ExcTest.GenException();
    }
    catch (IndexOutOfRangeException exc) {
      Console.WriteLine("Стандартное сообщение таково: ");
      Console.WriteLine(exc); // вызвать метод ToString()
      Console.WriteLine("Свойство StackTrace: " + exc.StackTrace);
      Console.WriteLine("Свойство Message: " + exc.Message);
      Console.WriteLine("Свойство TargetSite: " + exc.TargetSite);
    }
  Console.WriteLine("После блока перехвата исключения.");
  }
}

При выполнении этой программы получается следующий результат.

До генерирования исключения.
nums[0]: 0
nums[1]: 1
nums[2]: 2
nums[3]: 3
Стандартное сообщение таково: System.IndexOutOfRangeException: Индекс находился
вне границ массива.
    в ExcTest.genException() в <имя_файла>:строка 15
    в UseExcept.Main()в <имя_файла>:строка 29
Свойство StackTrace:  в ExcTest.genException()в <имя_файла>:строка 15
    в UseExcept.Main()в <имя_файла>:строка 29
Свойство Message:    Индекс    находился    вне    границ    массива.
Свойство TargetSite:    Void genException()
После блока перехвата исключения.

В классе Exception определяются четыре следующих конструктора:

public Exception()
public Exception(string сообщение)
public Exception(string сообщение, Exception внутреннее_исключение)
protected Exception(System.Runtime.Serialization.Serializationlnfo информация, System.Runtime.Serialization.StreamingContext контекст)

Первый конструктор используется по умолчанию. Во втором конструкторе указывается строка сообщение, связанная со свойством Message, которое имеет отношение к генерируемому исключению. В третьем конструкторе указывается так называемое внутреннее исключение. Этот конструктор используется в том случае, когда одно исключение порождает другое, причем внутреннее_исключение обозначает первое исключение, которое будет пустым, если внутреннее исключение отсутствует. (Если внутреннее исключение присутствует, то оно может быть получено из свойства InnerException, определяемого в классе Exception.) И последний конструктор обрабатывает исключения, происходящие дистанционно, и поэтому требует десериализации.

Следует также заметить, что в четвертом конструкторе класса Exception типы Serializationlnfo и StreamingContext относятся к пространству имен System. Runtime.Serialization.

Наиболее часто используемые исключения

В пространстве имен System определено несколько стандартных, встроенных исключений. Все эти исключения являются производными от класса SystemException, поскольку они генерируются системой CLR при появлении ошибки во время выполнения. В табл. 13.1 перечислены некоторые наиболее часто используемые стандартные исключения.

Таблица 13.1. Наиболее часто используемые исключения, определенные в пространстве имен System

Исключение                          Значение

ArrayTypeMismatchException - Тип сохраняемого значения несовместим с типом массива
DivideByZeroException - Попытка деления на нуль
IndexOutOfRangeException - Индекс оказался за границами массива
InvalidCastException - Неверно выполнено динамическое приведение типов
OutOfMemoryException - Недостаточно свободной памяти для дальнейшего выполнения программы. Это исключение может быть, например, сгенерировано, если для создания объекта с помощью оператора new не хватает памяти
OverflowException - Произошло арифметическое переполнение
NullReferenceException - Попытка использовать пустую ссылку, т.е. ссылку, которая не указывает ни на один из объектов

Большинство исключений, приведенных в табл. 13.1, не требует особых пояснений, кроме исключения NullReferenceException. Это исключение генерируется при попытке использовать пустую ссылку на несуществующий объект, например, при вызове метода по пустой ссылке. Пустой называется такая ссылка, которая не указывает ни на один из объектов. Для того чтобы создать такую ссылку, достаточно, например, присвоить явным образом пустое значение переменной ссылочного типа, используя ключевое слово null. Пустые ссылки могут также появляться и другими, менее очевидными путями. Ниже приведен пример программы, демонстрирующий обработку исключения NullReferenceException.

// Продемонстрировать обработку исключения NullReferenceException.
using System;
class X {
  int x;
  public X(int a) {
    x = a;
  }
  public int Add(X o) {
    return x + o.x;
  }
}
// Продемонстрировать генерирование и обработку
// исключения NullReferenceException.
class NREDemo {
  static void Main() {
    X p = new X(10);
    X q = null; // присвоить явным образом пустое
                //значение переменной q
    int val;
    try {
      val = p.Add(q); // эта операция приведет
       // к исключительной ситуации
    }
    catch (NullReferenceException) {
      Console.WriteLine("Исключение NullReferenceException!");
      Console.WriteLine("Исправление ошибки...n");
      // А теперь исправить ошибку,
      q = new X(9);
      val = p.Add(q);
    }
    Console.WriteLine("Значение val равно {0}", val);
  }
}

Вот к какому результату приводит выполнение этой программы.

Исключение NullReferenceException!
Исправление ошибки...
Значение val равно 19

В приведенном выше примере программы создается класс X, в котором определяются член х и метод Add(), складывающий значение члена х в вызывающем объекте со значением члена х в объекте, передаваемом этому методу в качестве параметра. Оба объекта класса X создаются в методе Main(). Первый из них (переменная р) инициализируется, а второй (переменная q) — нет. Вместо этого переменной q присваивается пустое значение. Затем вызывается метод р. Add() с переменной q в качестве аргумента. Но поскольку переменная q не ссылается ни на один из объектов, то при попытке получить значение члена q. х генерируется исключение NullReferenceException.

Оглавление книги


Генерация: 1.419. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз