Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.09.2011, 21:47   #1
Руслантус
Наркоман самоучка
Форумчанин
 
Аватар для Руслантус
 
Регистрация: 22.07.2007
Сообщений: 276
Счастье Обработка и описание исключений в библиотеке классов

Хотел бы узнать ваше мнение, насчёт того, как правильно обрабатывать исключения в библиотеке классов, и о каких исключениях сообщать в XML-комментариях.

Давайте рассмотрим надуманный пример:
Код:
        /// <summary>
        /// Создаёт экземпляр класса <see cref="MyObject"/> на основе информации из файла.
        /// </summary>
        /// <param name="pathToFile">Путь к файлу, который содержит информацию об объекте.</param>
        /// <returns>Экземпляр класса <see cref="MyObject"/>, созданный на основе информации из файла.</returns>
        /// <exception cref="System.ArgumentException">Значение параметра <paramref name="pathToFile"/> равно <see langword="null"/> или имеет нулевую длину.</exception>
        /// <exception cref="System.FormatException">Неправильный формат данных файла.</exception>
        public MyObject CreateMyObjectFromFile(string pathToFile)
        {
            if (string.IsNullOrEmpty(pathToFile))
            {
                throw new ArgumentException(..., "pathToFile");
            }

            string fileContent;

            using (FileStream fStream = new FileStream(pathToFile, FileMode.Open))
            using (StreamReader sReader = new StreamReader(fStream))
            {
                fileContent = sReader.ReadToEnd();
            }

            // Проверяем правильность данных.
            if (...)
            {
                throw new FormatException(...);
            }

            // Вычисляем MD5 хэш-значение для одного из параметров объекта.
            using (HashAlgorithm hashProvider = new MD5CryptoServiceProvider())
            {
                StringBuilder hashBuilder = new StringBuilder();
                ...
            }

            // Создаём и возвращаем экземпляр класса.
            MyObject myObject = ...;

            return myObject;
        }
И так, данный метод может с генерировать два типа исключения. Если брать во внимание сторонние классы, то они могут с генерировать несколько типов исключений. Так вот, как поступить?

- Оставить как есть - это приемлемый вариант.
- Оставить как есть, но в XML-комментарии добавить все возможные исключения сторонних классов, просто скопировав их описание из документации.
#include <мозг.h>
Руслантус вне форума Ответить с цитированием
Старый 21.09.2011, 21:47   #2
Руслантус
Наркоман самоучка
Форумчанин
 
Аватар для Руслантус
 
Регистрация: 22.07.2007
Сообщений: 276
По умолчанию

- Сделать обёртку try-catch-finally над каждым потенциально-опасным вызовом. В catch сделать повторную генерацию исключения с пояснением ошибки и задать начальное исключение. В XML-комментариях указать все эти возможные исключения:
Код:
        /// <summary>
        /// Создаёт экземпляр класса <see cref="MyObject"/> на основе информации из файла.
        /// </summary>
        /// <param name="pathToFile">Путь к файлу, который содержит информацию об объекте.</param>
        /// <returns>Экземпляр класса <see cref="MyObject"/>, созданный на основе информации из файла.</returns>
        /// <exception cref="System.ArgumentException">Значение параметра <paramref name="pathToFile"/> равно <see langword="null"/> или имеет нулевую длину.</exception>
        /// <exception cref="System.FormatException">Неправильный формат данных файла.</exception>
        /// <exception cref="System.Security.SecurityException">У вызывающего объекта отсутствует необходимое разрешение доступа к файлу.</exception>
        /// <exception cref="System.IO.IOException">Произошла ошибка ввода-вывода, при попытки считать данные файла.</exception>
        /// <exception cref="System.InvalidOperationException">Ошибка при вычисления MD5 хэш-значение, так как политика FIPS-совместимого алгоритма не задействована.</exception>
        public MyObject CreateMyObjectFromFile(string pathToFile)
        {
            if (string.IsNullOrEmpty(pathToFile))
            {
                throw new ArgumentException(..., "pathToFile");
            }

            string fileContent;
            FileStream fStream;
            StreamReader sReader;

            try
            {
                fStream = new FileStream(pathToFile, FileMode.Open);
                sReader = new StreamReader(fStream);

                fileContent = sReader.ReadToEnd();
            }
            catch (SecurityException ex)
            {
                throw new SecurityException("Не удалось получить доступ к файлу, который хранить информацию об объекте.", ex);
            }
            catch (IOException ex)
            {
                throw new IOException("Не удалось считать данные из файла, который хранить информацию об объекте.", ex);
            }
            finally
            {
                if (sReader != null)
                {
                    sReader.Dispose();
                }

                if (fStream != null)
                {
                    fStream.Dispose();
                }
            }

            // Проверяем правильность данных.
            if (...)
            {
                throw new FormatException(...);
            }

            HashAlgorithm hashProvider;

            try
            {
                // Вычисляем MD5 хэш-значение для одного из параметров объекта.
                hashProvider = new MD5CryptoServiceProvider();

                StringBuilder hashBuilder = new StringBuilder();
                ...
            }
            catch (InvalidOperationException ex)
            {
                throw new InvalidOperationException("Не удалось вычислить MD5 хэш-значение для одного из параметров объекта.", ex);
            }
            finally
            {
                if (hashProvider != null)
                {
                    hashProvider.Dispose();
                }
            }

            // Создаём и возвращаем экземпляр класса.
            MyObject myObject = ...;

            return myObject;
        }
#include <мозг.h>
Руслантус вне форума Ответить с цитированием
Старый 22.09.2011, 09:47   #3
Guy
Форумчанин
 
Регистрация: 15.12.2010
Сообщений: 398
По умолчанию

1) Кидать своё исключение где в innerException сувать то которое было вызвано внутри.
2) А так 2-й вариант лучше где ты сам ловшишь исключения из других функций и уже по своей логике кидаешь выше отсальные исключения из xml комментариев твоих

Если чесно так особо не порасписываешься тока если пишешь что то базовое что все пользовать будут
Guy вне форума Ответить с цитированием
Старый 22.09.2011, 20:28   #4
Руслантус
Наркоман самоучка
Форумчанин
 
Аватар для Руслантус
 
Регистрация: 22.07.2007
Сообщений: 276
По умолчанию

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

Кто, что ещё думает?
#include <мозг.h>
Руслантус вне форума Ответить с цитированием
Старый 23.09.2011, 13:12   #5
ds.Dante
Старожил
 
Аватар для ds.Dante
 
Регистрация: 06.08.2009
Сообщений: 2,992
По умолчанию

Вместо этого:
Код:
FileStream fStream;
StreamReader sReader;

try
{
    fStream = new FileStream(pathToFile, FileMode.Open);
    sReader = new StreamReader(fStream);
    [Работа с файлом]
}
catch (Exception)
{
    [Обработка ошибки]
}
finally
{
    if (sReader != null)
    {
        sReader.Dispose();
    }

    if (fStream != null)
    {
        fStream.Dispose();
    }
}
проще писать так:
Код:
try
{
    using (FileStream fStream = new FileStream(pathToFile, FileMode.Open),
        StreamReader sReader = new StreamReader(fStream))
    {
        [Работа с файлом]
    }
}
catch (Exception)
{
    [Обработка ошибки]
}
Все файлы и потоки корректно закроются независимо от возможных исключений.

Последний раз редактировалось ds.Dante; 23.09.2011 в 13:15.
ds.Dante вне форума Ответить с цитированием
Старый 23.09.2011, 13:32   #6
Руслантус
Наркоман самоучка
Форумчанин
 
Аватар для Руслантус
 
Регистрация: 22.07.2007
Сообщений: 276
По умолчанию

Я же не об этом спрашиваю. Это просто пример. Если смотреть со стороны, что проще и удобней, то лучше написать так:
Код:
File.ReadAllText(...);
#include <мозг.h>
Руслантус вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обработка исключений Ckomoroh Общие вопросы Delphi 6 21.03.2011 08:52
обработка исключений user666 Помощь студентам 36 27.08.2010 18:00
обработка исключений scray PHP 3 15.05.2010 15:02
описание классов многочленов Sined121 Помощь студентам 0 03.12.2009 16:23
Описание диаграммы классов Krechet Общие вопросы Delphi 4 07.05.2009 13:53