public class MyException: Exception
{
public MyException()
{ }
public MyException (string message): base(message)
{ }
public MyException (string message, Exception e): base(message, e)
{ }
}
Минимум того, что нужно сделать, определяя свои исключения, — это задать три конструктора класса, вызывающие соответствующие конструкторы базового класса Exception.
В классе Excepts, методом которого является наш образец Pattern, определим следующие поля класса:
Random rnd = new Random();
int level = -10;
bool Success; //true — нормальное завершение
int count =1; // число попыток выполнения
const int maxcount =3;
Определим теперь методы, вызываемые в теле охраняемого блока:
void MakeJob()
{
Console.WriteLine("Подготовительные работы завершены");
}
bool CheckDanger()
{
//проверка качества и возможности продолжения работ
int low = rnd.Next(level,10);
if (low > 6) return (false);
return(true);
}
void MakeLastJob()
{
Console.WriteLine("Все работы завершены успешно");
}
В классе Testing зададим метод, вызывающий метод Pattern;
public void TestPattern ()
{
Excepts ex1 = new Excepts ();
try
{
ex1.Pattern ();
}
catch (Exception e)
{
Console.WriteLine("исключительная ситуация при вызове Pattern");
Console.WriteLine(e.ToString ());
}
}
Обратите внимание, что вызов метода Pattern находится внутри охраняемого блока. Поэтому, когда Pattern не справится с обработкой исключительной ситуации, ее обработку возьмет на себя универсальный обработчик, стоящий за try-блоком. На рис. 23.6 показаны три варианта запуска метода TestPattern. в одном из них исключительной ситуации при вызове метода Pattern вообще не возникало, в другом — ситуация возникала, но коррекция обработчика исключения помогла и при повторе выполнения охраняемого блока в Pattern все прошло нормально. В третьем варианте метод Pattern не смог справиться с исключительной ситуацией, и она обрабатывалась в catch-блоке метода TestPattern.
Рис. 23.6. Обработка исключительных ситуаций. Три случая
Класс Exception
Рассмотрим устройство базового класса Exception, чтобы понять, какую информацию может получить обработчик исключения, когда ему передается объект, задающий текущее исключение. Основными свойствами класса являются:
• Message — строка, задающая причину возникновения исключения. Значение этого свойства устанавливается при вызове конструктора класса, когда создается объект, задающий исключение;
• HeipLink — ссылка (URL) на файл, содержащий подробную справку о возможной причине возникновения исключительной ситуации и способах ее устранения;
• InnerException — ссылка на внутреннее исключение. Когда обработчик выбрасывает новое исключение для передачи обработки на следующий уровень, то текущее исключение становится внутренним для вновь создаваемого исключения;
• Source — имя приложения, ставшего причиной исключения;
• StackTrace — цепочка вызовов — методы, хранящиеся в стеке вызовов в момент возникновения исключения;
• Targetsite — метод, выбросивший исключение.
Из методов класса отметим метод GetBaseException. При подъеме по цепочке вызовов он позволяет получить исходное исключение — первопричину возникновения последовательности выбрасываемых исключений.
Класс имеет четыре конструктора, из которых три уже упоминались. Один из них — конструктор без аргументов, второй — принимает строку, становящуюся свойством Message, третий — имеет еще один аргумент: исключение, передаваемое свойству InnerException.
В предыдущий пример я внес некоторые изменения. В частности, добавил еще один аргумент при вызове конструктора исключения в catch-блоке метода Pattern;
throw(new MyException("Все попытки Pattern безуспешны", me));
В этом случае у создаваемого исключения заполняется свойство InnerExceptions. Для слежения за свойствами исключений я добавил метод печати всех свойств, вызываемый во всех обработчиках исключений:
static public void PrintProperties (Exception e)
{
Console.WriteLine("Свойства исключения: ");
Console.WriteLine("Targetsite = {0}", e.Targetsite);
Console.WriteLine("Source = {0}", e.Source);
Console.WriteLine("Message = {0}",e.Message);
if (e.InnerException == null)