Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Хотелось бы разобраться с исключениями 
:(
    Опции темы
Primordial
Дата 18.11.2013, 02:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 7.4.2013

Репутация: нет
Всего: нет



Доброго времени суток! Перехожу от теории к практике и хотелось бы в первом приближении определиться с использованием исключений. Как я понимаю, разработка грамотного кода подразумевает следующее:
1. Если уже существует класс исключения, уместного в данной ситуации, необходимо использовать его. Например, ArgumentException, в случае, если передаваемые в метод аргументы по какой-либо причине не подходят и т.д.
2. Определять свои пользовательские классы исключений следует в случае, если подходящих встроенных не нашлось. (Как вообще определить когда и для чего вводить свои типы исключений? Как, например, отреагировать на то, что класс читающий конфиг не нашел или не смог открыть файл: каким-либо из встроенных или пользовательским?)
3. В случае если я ввожу свои типы исключений, для каждой возможной ошибки мне следует создать свой тип (Или же можно ограничиться одним, общим для какой-либо задачи типом? Например, все ошибки, которые могут возникнуть при чтении конфига, выбрасывать как исключения одного типа с соответствующими описаниями). 

Верны ли приведенные выше суждения?
PM MAIL   Вверх
dzaraev
Дата 19.11.2013, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 12.1.2013

Репутация: 1
Всего: 1



1. разумеется
2. наследуете от класса Exception или от одного из его наследников

Цитата(Primordial @  18.11.2013,  02:39 Найти цитируемый пост)
 (Как вообще определить когда и для чего вводить свои типы исключений? Как, например, отреагировать на то, что класс читающий конфиг не нашел или не смог открыть файл: каким-либо из встроенных или пользовательским?)

Ну вы же сами выше написали: когда не хватает базовых - вводите свои.

3. Исключение это такой же класс, который должен иметь какую-то одну "обязанность". "Обязанностью" в данном случая является описание ошибки. Какие именно классы плодить - зависит от того, какие ошибки вы хотите различать и обрабатывать в коде (например ловить в try/catch). Если обработчик ошибки в catch блоке "понимает" что надо делать при InvalidOperationException - значит хватит и этого эксепшена. Если, нет - пусть ловит более конкретный эксепшн, например MyEpicFailException.
Обработка в блоке catch базового класса Exception - плохая практика, т.к. вы вряд ли гарантированно можете восстановить согласованное состояние программы во всех возможных случаях. Поэтому обрабатывают более конкретные исключения, которые ожидаемо могут быть выброшены в блоке try. Т.е. те ошибки, которые вы знаете как "починить". 
Допустим есть код 
Код

try
{
     DoMyCriticalTask();
}
catch (InvalidOperationException ex)
{
    //весьма сложно предусмотреть все причины падений и выполнить соответствующую "починку"
}

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

try
{
     DoMyCriticalTask();
}
catch (MyEpicFailException ex)
{
    //семантика исключения более точна, а значит можно выполнить более адекватное восстановление нормальной работы программы.
}

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

try
{
     DoMyCriticalTask();
}
catch (MySpecificFailReasonException ex)
{
    //более точная ошибка, более конкретный код восстановления.
}
catch (MyEpicFailException ex)
{
    //когда это предусмотренная нами ошибка, но точная причина может быть неизвестна, код восстановления может быть другим
}



--------------------
Если вопрос решён - помечайте тему.  
PM MAIL   Вверх
Primordial
Дата 24.11.2013, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 7.4.2013

Репутация: нет
Всего: нет



Цитата

Обработка в блоке catch базового класса Exception - плохая практика, т.к. вы вряд ли гарантированно можете восстановить согласованное состояние программы во всех возможных случаях.

Тогда, быть может, вылавливать базовое исключение последним, после обработки всех ожидаемых типов ошибок и, поскольку не понятно в чем проблема, укладывать приложение?

В свое время, когда я активно писал на Delphi, я заводил класс-предок исключений, скажем для бизнес-логики, в котором у меня было поле типа "строка" с уникальным идентификатором ошибки (использовался GUID). Т.о. я всегда мог отследить в каком месте кода возникло исключение посредством поиска по коду проекта. Разумеется, при наличии UI, пользователю показывалось осмысленное сообщение. Есть ли смысл делать под .net что-то похожее? Насколько такой подход распространен?
PM MAIL   Вверх
jonie
Дата 24.11.2013, 21:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Цитата(Primordial @  24.11.2013,  16:26 Найти цитируемый пост)

Тогда, быть может, вылавливать базовое исключение последним, после обработки всех ожидаемых типов ошибок и, поскольку не понятно в чем проблема, укладывать приложение?
Так и делают, только не отлавливают, а подписываются на соотвествующее событие домена и что-то делают вроде лога или почты. Можно также снять минидамп и отослать его на анализ.

короче читать это: http://msdn.microsoft.com/en-us/library/ms...=vs.100%29.aspx
(ранее было доступно в виде pdf)


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
dzaraev
Дата 25.11.2013, 06:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 12.1.2013

Репутация: 1
Всего: 1



Цитата(Primordial @  24.11.2013,  15:26 Найти цитируемый пост)
В свое время, когда я активно писал на Delphi, я заводил класс-предок исключений, скажем для бизнес-логики, в котором у меня было поле типа "строка" с уникальным идентификатором ошибки (использовался GUID). Т.о. я всегда мог отследить в каком месте кода возникло исключение посредством поиска по коду проекта. Разумеется, при наличии UI, пользователю показывалось осмысленное сообщение. Есть ли смысл делать под .net что-то похожее? Насколько такой подход распространен? 

Не скажу за всех, но я предпочитаю просто сохранять стек (свойство Exception.StackTrace), это даёт возможность не просто найти место выброса исключения, но и увидеть "историю" его появления.
Код

internal class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Debug.WriteLine("Попытка - не пытка...");
                ProblemMethod();
            }
            catch (InvalidOperationException ex)
            {
                Debug.WriteLine("-------------------У нас проблемы:-------------------");
                Debug.WriteLine(ex.StackTrace);
                Debug.WriteLine("-----------------------------------------------------");
            }
        }

        static void ProblemMethod()
        {
            throw new InvalidOperationException("Всё пропало!");
        }
    }


Output:
Код

Попытка - не пытка...
A first chance exception of type 'System.InvalidOperationException' occurred in ConsoleApplication6.exe
-------------------У нас проблемы:-------------------
   в ConsoleApplication6.Program.ProblemMethod() в D:\Work\sandbox\ConsoleApplication6\ConsoleApplication6\Program.cs:строка 29
   в ConsoleApplication6.Program.Main(String[] args) в D:\Work\sandbox\ConsoleApplication6\ConsoleApplication6\Program.cs:строка 17
-----------------------------------------------------

--------------------
Если вопрос решён - помечайте тему.  
PM MAIL   Вверх
jonie
Дата 25.11.2013, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 6
Всего: 118



Цитата(dzaraev @  25.11.2013,  07:54 Найти цитируемый пост)

Не скажу за всех, но я предпочитаю просто сохранять стек (свойство Exception.StackTrace), 

Уже давно люди придумали готовые логгер либы, вроде nlog-а, где формат вывода можно настроить не в коде 8-)
Ну а при наличии реально проблем как я уже говорил - делайте Debugger.Break (например) - это позволит снять дамп, ну или Enviroment.FailFast после снятия дампа и записи в лог...


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
dzaraev
Дата 25.11.2013, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 149
Регистрация: 12.1.2013

Репутация: 1
Всего: 1



Цитата(jonie @  25.11.2013,  11:35 Найти цитируемый пост)
Уже давно люди придумали готовые логгер либы, вроде nlog-а, где формат вывода можно настроить не в коде 8-)

Спасибо, я в курсе. Если вы про черточки  - это просто для примера )) Суть самого пример в том, что не нужен какой-то гуид, чтобы понять по логу - где случился фейл.


--------------------
Если вопрос решён - помечайте тему.  
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0491 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.