Должны ли мои пользовательские исключения наследовать исключение, подобное им, или просто наследовать от исключения? - PullRequest
9 голосов
/ 23 июня 2009

Я создаю несколько пользовательских исключений в моем приложении.

Если у меня возникает исключение, которое выдается после проверки состояния аргумента, или у меня есть исключение, которое выдается после проверки того, что int находится в надлежащем диапазоне, если мои исключения наследуют ArgumentException и IndexOutOfRangeException или они просто наследуют Исключение?

Ответы [ 10 ]

11 голосов
/ 23 июня 2009

Поскольку наследование используется для указания того, какие исключения следует отлавливать, вы должны соблюдать это в первую очередь при принятии решения.

Представьте себе исключение IOException, содержащее дополнительную информацию, или исключение ArgumentException, отличное от ArgumentOutOfRangeException или ArgumentNullException.

7 голосов
/ 23 июня 2009

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

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

Как, например, throw new IntOutOfProperRangeException(); значительно отличается от throw new ArgumentOutOfRangeException("The int value was too large?");

4 голосов
/ 23 июня 2009

Я думаю, что всегда безопаснее создать новый тип исключения. Если вам когда-нибудь понадобится изменить способ обработки, вам будет легче находить случаи, когда вы это делаете или, возможно, решаете. Найти MyException намного проще, чем найти конкретный случай ArgumentOutOfRangeException. Похоже, вы можете предоставить некоторую дополнительную информацию об исключении, и создать исключение не так уж и много.

Также я склонен наследовать базовый класс приложения, такой как MyBaseException, и обязательно добавлять комментарии XML для исключения / с.

2 голосов
/ 23 июня 2009

Лично, если у меня есть индексатор и значение индекса выходит за пределы диапазона, я бы просто выбросил существующее исключение IndexOutOfRangeException, я бы не стал его наследовать.

Если вы говорите только о похожих, но не совсем одинаковых исключениях, взгляните на шаблон, представленный в фреймворке. Не похоже, что в этом есть смысл, наследование описывает отношения «есть».

2 голосов
/ 23 июня 2009

Мне просто любопытно, почему бы вам не использовать Исключения, которые уже есть? Похоже, что эти исключения именно то, что вам нужно, почему вы против их использования?

1 голос
/ 23 июня 2009

ИМХО, нет проблем с наследованием из другого исключения. Это делает еще более понятной цель этого исключения. Но убедитесь, что все, что относится к ParentException, также относится и к ChildException, который вы создали. В противном случае вы можете столкнуться с проблемой "Квадрат расширяет прямоугольник" ...

1 голос
/ 23 июня 2009

Если вам не нужно добавлять какие-либо дополнительные данные к исключению, я бы просто использовал собственные исключения .NET, такие как IndexOutOfRangeException.

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

0 голосов
/ 23 июня 2009

Я думаю, что все зависит от того, хотите ли вы перехватить ваше исключение ArgumentNotInPersitableState как ArgumentOutOfRange. Если будет такой блок catch (или если вы пишете каркас, который предположительно будет использоваться другими), тогда да, вы должны наследовать соответствующий тип исключения.

0 голосов
/ 23 июня 2009

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

try 
{
}
catch (Exception ex)
{
}

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

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

Например, у меня есть приложение enigineering, которое определяет размеры систем ременного привода. DLL также доступна для использования другими людьми. У меня есть исключение приложения, которое выбрасывается при возникновении ошибки в выборе. Причиной ошибки может быть множество причин (неправильная скорость привода, неправильные требования к лошадиным силам и т. Д.). Поскольку существует множество причин сбоя, исключение из пользовательского приложения позволяет мне предоставить конкретные сведения об ошибке.

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

Если ваш наследующий класс Exception убедитесь, что в базовом классе реализованы конструкторы, которые имеют сообщение, сообщение + внутреннее исключение и сериализованное исключение.

Вот пример, который у меня есть.

/// <summary>
/// Drive error exception class. Thrown when a drive selection error has occured.
/// </summary>
[Serializable]
public class DriveException : ApplicationException
{
    /// <summary>
    /// Default constructor.
    /// </summary>
    public DriveException()
    {
    }
    /// <summary>
    /// Constructor used with a message.
    /// </summary>
    /// <param name="message">String message of exception.</param>
    public DriveException(string message)
        : base(message)
    {
    }
    /// <summary>
    /// Constructor used with a message and an inner exception.
    /// </summary>
    /// <param name="message">String message of exception.</param>
    /// <param name="inner">Reference to inner exception.</param>
    public DriveException(string message, Exception inner)
        : base(message, inner)
    {
    }
    /// <summary>
    /// Constructor used in serializing the data.
    /// </summary>
    /// <param name="info">Data stored to serialize/de-serialize</param>
    /// <param name="context">Defines the source/destinantion of the straeam.</param>
    public DriveException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}
0 голосов
/ 23 июня 2009

Почти всегда я использую IllegalArgumentException (нулевые значения и / или значения вне диапазона) и IllegalStateException для чего-либо не более конкретного, чем IOException, SQLException, Null ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...