Добавить в цитаты Настройки чтения

Страница 346 из 371

• Если в методе CheckDanger выясняется, что нормальное продолжение вычислений невозможно, то выбрасывается исключение класса MyException. Оно перехватывается обработчиком исключения, стоящим за try-блоком, поскольку класс MyException указан как класс формального аргумента.

• Для простоты приведен только один catch-блок. В общем случае их может быть несколько, но все они строятся по единому образцу. Предполагается, что обработчик исключения может сделать несколько попыток исправить ситуацию, после чего повторно выполняется охраняемый блок. Если же число попыток, за которым следит переменная count, превосходит максимально допустимое, то обработчик выбрасывает новое исключение, задавая дополнительную информацию и передавая тем самым обработку ошибки на следующий уровень — вызываемой программе.

• Когда число попыток еще не исчерпано, обработчик исключения переменной Success дает значение false, гарантирующее повтор выполнения try-блока, увеличивает счетчик числа попыток и пытается исправить ситуацию.

• Как видите, эта схема реализует два корректных исхода обработки исключительной ситуации — Retry и Rescue — повтору с надеждой выполнить обязательства и передачи управления вызывающей программе, чтобы она предприняла попытки исправления ситуации, когда вызванная программа не смогла с этим справиться.

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

Определим первым делом собственный класс исключений:

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) на файл, содержащий подробную справку о возможной причине возникновения исключительной ситуации и способах ее устранения;

• I

• Source — имя приложения, ставшего причиной исключения;

• StackTrace — цепочка вызовов — методы, хранящиеся в стеке вызовов в момент возникновения исключения;

• Targetsite — метод, выбросивший исключение.

Из методов класса отметим метод GetBaseException. При подъеме по цепочке вызовов он позволяет получить исходное исключение — первопричину возникновения последовательности выбрасываемых исключений.

Класс имеет четыре конструктора, из которых три уже упоминались. Один из них — конструктор без аргументов, второй — принимает строку, становящуюся свойством Message, третий — имеет еще один аргумент: исключение, передаваемое свойству I

В предыдущий пример я внес некоторые изменения. В частности, добавил еще один аргумент при вызове конструктора исключения в catch-блоке метода Pattern;

throw(new MyException("Все попытки Pattern безуспешны", me));

В этом случае у создаваемого исключения заполняется свойство I

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.I

        Console.WriteLine("I

    else Console.WriteLine("I

        e. I

    Console.WriteLine("StackTrace = {0}", e.StackTrace);

    Console.WriteLine("GetBaseException = {0}",

        e. GetBaseException ());

}

Из-за громоздкости не привожу результаты, но отмечу, что они соответствуют описанию, приведенному в тексте лекции.

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

• обработка исключений должна быть направлена не столько на уведомление о возникновении ошибки, сколько на корректировку возникшей ситуации;

• если исправить ситуацию не удается, то программа должна быть прервана так, чтобы не были получены некорректные результаты, не удовлетворяющие спецификациям программы.

24. Организация интерфейса и рисование в формах

Организация интерфейса. Шаблоны форм. Заселение формы элементами управления. Классы элементов управления. Примеры классов. Класс ListBox. Наследование форм. Организация меню, главное меню. Инструментальные панели с кнопками. Рисование в формах. Классы рисования. Кисти и перья.