Литмир - Электронная Библиотека
Содержание  
A
A

Большинство исключений, приведенных в табл. 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.Получение производных классов исключений

Несмотря на то что встроенные исключения охватывают наиболее распространенные программные ошибки, обработка исключительных ситуаций в C# не ограничивается только этими ошибками. В действительности одна из сильных сторон принятогов C# подхода к обработке исключительных ситуаций состоит в том, что в этом языкедопускается использовать исключения, определяемые пользователем, т.е. тем, кто программирует на С#. В частности, такие специальные исключения можно использоватьдля обработки ошибок в собственном коде, а создаются они очень просто. Для этогодостаточно определить класс, производный от класса Exception. В таких классах совсем не обязательно что-то реализовывать — одного только их существования в системе типов уже достаточно, чтобы использовать их в качестве исключений.

ПРИМЕЧАНИЕВ прошлом специальные исключения создавались как производные от классаApplication.Exception, поскольку эта иерархия классов была первоначально зарезервирована для исключений прикладного характера. Но теперь корпорация Microsoft не рекомендует этого делать, а вместо этого получать исключения, производные от класса Exception.Именно по этой причине данный подход и рассматривается в настоящей книге.

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

Рассмотрим пример программы, в которой используется исключение специальноготипа. Напомним, что в конце главы 10 был разработан класс RangeArray, поддерживающий одномерные массивы, в которых начальный и конечный индексы определяются пользователем. Так, например, вполне допустимым считается массив, индексируемый в пределах от -5 до 27. Если же индекс выходил за границы массива, то для обработки этой ошибки в классе RangeArray была определена специальная переменная.Такая переменная устанавливалась и проверялась после каждой операции обращенияк массиву в коде, использовавшем класс RangeArray. Безусловно, такой подход к обработке ошибок "неуклюж" и чреват дополнительными ошибками. В приведенномниже улучшенном варианте класса RangeArray обработка ошибок нарушения границмассива выполняется более изящным и надежным способом с помощью специальногенерируемого исключения.

// Использовать специальное исключение для обработки// ошибок при обращении к массиву класса RangeArray.using System;

// Создать исключение для класса RangeArray.class RangeArrayException : Exception { / Реализовать все конструкторы класса Exception. Такие конструкторы просто реализуют конструктор базового класса. А поскольку класс исключения RangeArrayException ничего не добавляет к классу Exception, то никаких дополнительных действий не требуется. / public RangeArrayException() : base)) { }public RangeArrayException(string str) : base(str) { }public RangeArrayException(string str, Exception inner) : base (str, inner) { }protected RangeArrayException(System.Runtime.Serialization.SerializationInfo si,System.Runtime.Serialization.StreamingContext sc) :base(si, sc) { }// Переопределить метод ToString() для класса исключения RangeArrayException.public override string ToString() { return Message;}

}

// Улучшенный вариант класса RangeArray.class RangeArray { // Закрытые данные. int[] a; // ссылка на базовый массив int lowerBound; // наименьший индекс int upperBound; // наибольший индекс// Автоматически реализуемое и доступное только для чтения свойство Length.public int Length { get; private set; }// Построить массив по заданному размеруpublic RangeArray(int low, int high) { high++; if(high <= low) { throw new RangeArrayException("Нижний индекс не меньше верхнего."); } а = new int[high - low]; Length = high - low; lowerBound = low; upperBound = --high;}// Это индексатор для класса RangeArray.public int this[int index] { // Это аксессор get. get { if(ok(index)) { return a[index - lowerBound]; } else { throw new RangeArrayException("Ошибка нарушения границ."); } } // Это аксессор set. set { if(ok(index)) { a[index - lowerBound] = value; } else throw new RangeArrayException("Ошибка нарушения границ."); }}// Возвратить логическое значение true, если// индекс находится в установленных границах.private bool ok(int index) { if(index >= lowerBound S index <= upperBound) return true; return false;}

}

// Продемонстрировать применение массива с произвольно// задаваемыми пределами индексирования.class RangeArrayDemo { static void Main() { try { RangeArray ra = new RangeArray(-5, 5); RangeArray ra2 = new RangeArray(1, 10); // Использовать объект ra в качестве массива. Console.WriteLine("Длина массива ra: " + ra.Length); for(int i = -5; i <= 5; i++) ra[i] = i; Console.Write("Содержимое массива ra: "); for(int i = -5; i <= 5; i++) Console.Write(ra[i] + " "); Console.WriteLine("\n"); // Использовать объект ra2 в качестве массива. Console.WriteLine("Длина массива ra2: " + ra2.Length); for(int i = 1; i <= 10; i++) ra2[i] = i; Console.Write("Длина массива ra2: "); for(int i = 1; i <= 10; i++) Console.Write(ra2[i] + " "); Console.WriteLine("\n"); } catch (RangeArrayException exc) { Console.WriteLine(exc); } // А теперь продемонстрировать обработку некоторых ошибок. Console.WriteLine("Сгенерировать ошибки нарушения границ."); // Использовать неверно заданный конструктор. try { RangeArray ra3 = new RangeArray(100, -10); // Ошибка! } catch (RangeArrayException exc) { Console.WriteLine(exc); } // Использовать неверно заданный индекс. try { RangeArray ra3 = new RangeArray(-2, 2); for(int i = -2; i <= 2; i++) ra3[i] = i; Console.Write("Содержимое массива ra3: "); for(int i = -2; i <= 10; i++) // сгенерировать ошибку нарушения границ Console.Write(ra3[i] + " "); } catch (RangeArrayException exc) { Console.WriteLine(exc); }}

88
{"b":"245736","o":1}