Главная · Карта сайта · Поиск · Статьи · Компьютерные курсы · Обучающие программы · Открытые проекты · Веб-программирование · Создание интернет-сайта · Полезные ссылки · Глоссарий · Контакты · Декабрь 09 2016 22:16:39
Последнее опубликованное

Что такое Model-View-Controller
Pattern Model-View-Controller

Как создать свой веб-сайт
Как создать свой сайт в интернете

Разное
Статистика

Программирование на C#. Исключения (каскадная обработка)


[Назад] [Следующая страница]

5.4. Распределение ответственности

Может случиться так, что ответственность за обработку исключительных ситуаций распределена по приложению равномерно: на каждом архитектурном уровне обрабатываются только “свои” исключения, а все остальные отправляются дальше “наверх”. Конструкция try-catch позволяет выбирать, какого типа исключения обрабатывать. Более того, эта конструкция позволяет настроить каскадную обработку исключительных ситуаций: от более общих к более специфичным. Делается это за счет определения нескольких блоков catch в рамках одного try. Пример определения своего собственного класса – исключения и обработки различных видов исключительных ситуаций приведен ниже:

using System;
using System.Windows.Forms;
namespace CSharpQuickGuide
{
    //Определение собственного исключения
    public class MyException : Exception
    {
        //Рекомендуется, помимо специфичных, опрелять все
        //конструкторы, имеющиеся у базового класса Exception.
        //Тем самым, вы можете быть уверены, что ваш класс
        //можно будет использовать в любых ситуациях.
        public MyException()
            : base() { }

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

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

        public MyException(System.Runtime.Serialization.SerializationInfo info,
             System.Runtime.Serialization.StreamingContext context)
            : base(info, context) { } 
    }

    public static class Sample05
    {
        public static void Test()
        {
            //Возбуждается исключение ArgumentNullException
            //Сообщение: "ArgumentNullException" и "Finally"
            ExceptionSample(null);
            //Возбуждается исключение MyException
            //Сообщение: "MyException" и "Finally"
            ExceptionSample(string.Empty);
        }

        public static void ExceptionSample(object o)
        {
            try
            {
                if (o == null)
                    throw new ArgumentNullException("Argument 'o' is null!");
 
                //Проверка: является ли строка пустой или состоит из одних пробелов.
                if (string.IsNullOrWhiteSpace(o.ToString()))
                    throw new MyException("Argument 'o' has no 'string' presentation!"); 
            }
            catch (MyException ex)
            {
                MessageBox.Show(ex.Message, "MyException");
            }
            catch (ArgumentNullException ex)
            {
                MessageBox.Show(ex.Message, "ArgumentNullException");
            }
            finally
            {
                MessageBox.Show("Finally");
            }
        }
    }
}

Если вы все-таки хотите обрабатывать все виды исключений вплоть до экземпляров базового объекта System.Exception, то добавьте их в порядке убывания специализации (от производного к базовому), как показано ниже:

        public static void ExceptionSample(object o)
        {
            try
            {
                if (o == null)
                    throw new ArgumentNullException("Argument 'o' is null!");
 
                if (string.IsNullOrWhiteSpace(o.ToString()))
                    throw new MyException("Argument 'o' has no 'string' presentation!"); 
            }
            catch (MyException ex)
            {
                MessageBox.Show(ex.Message, "MyException");
            }
            catch (ArgumentNullException ex)
            {
                MessageBox.Show(ex.Message, "ArgumentNullException");
            }
            catch (ArgumentException ex)
            {
                MessageBox.Show(ex.Message, "ArgumentException");
            }
            catch
            {
                MessageBox.Show("Exception", "AnyException");
            }
            finally
            {
                MessageBox.Show("Finally");
            }
        }

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

        public static void ExceptionSample(object o)
        {
            try
            {
                if (o == null)
                    throw new ArgumentNullException("Argument 'o' is null!");
 
                if (string.IsNullOrWhiteSpace(o.ToString()))
                    throw new MyException("Argument 'o' has no 'string' presentation!"); 
            }
            catch (ArgumentException ex)
            {
                MessageBox.Show(ex.Message, "ArgumentException");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Exception");
            }
            //Сюда управление никогда не перейдет, поскольку на блоке
            //catch (Exception ex) обработка будет закончена!
            //A previous catch clause already catches all exceptions of this 
            //or of super type ('System.Exception')
            catch (MyException ex)
            {
                MessageBox.Show(ex.Message, "MyException");
            }
            //Сюда управление также никогда не перейдет, даже если убрать блок
            //catch (Exception ex), поскольку ArgumentException является базовым
            //для класса ArgumentNullException!
            //A previous catch clause already catches all exceptions of this 
            //or of super type ('System.ArgumentException')
            catch (ArgumentNullException ex)
            {
                MessageBox.Show(ex.Message, "ArgumentNullException");
            }
            finally
            {
                MessageBox.Show("Finally");
            }
        }

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

        public static void ExceptionSample(object o)
        {
            try
            {
                //Выполнение действий, которые могут привести к
                //возникновению исключительной ситуации
                proceed(o);
            }
            catch (Exception ex)
            {
                //1. Регистрация исключения в журнале событий приложения.
                LogException(ex);

                //2. Повторное возбуждение исключения с целью его перехвата
                //   и обработки на более высоком архитектурном уровне программы.

                //Не делайте так!
                //throw ex;
                //Поскольку таким образом информация о первоначальном источнике ошибки
                //(proceed) в свойстве ex.StackTracer будет утеряна!

                //Повторно исключение следует возбуждать следующим образом:
                //(без обнуления стека трассировки)
                throw;
            }
        }

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



[Назад] [Следующая страница]

Компьютерные курсы и курсы программирования
Основы программирования

Курс для начинающих программистов на C# и VB.NET.

SQL 25™

Построение SQL запросов и работа с базой данных.

C# Quick Guide™

Программирование на C#. Краткое руководство.

RegEx

Применение регулярных выражений.

Plug-in архитектура

Примеры программной Plug-in архитектуры.

XML и его расширения

Язык разметки XML и его расширения с примерами.

HTML и разметка гипертекста

Языки HTML, XHTML и CSS с примерами разметки.

Основы веб-дизайна

Основы веб-дизайна: решения типовых задач верстки.

Программирование на PHP

Руководство по программированию на PHP для начинающих.

Справочные материалы

Шаблоны проектирования
Каталог шаблонов проектирования программных компонентов.

Рефакторинг кода
Каталог приемов рефакторинга программного кода.

Гость
Имя

Пароль



Забыли пароль?
Запросите новый здесь
.
Coding Craft. Все права защищены © 2011. Проект Инициативного Народного Фронта Образования - ИНФО-проект.