Когда лучше не создавать пользовательских исключений?


Я сделал компонент, который вызывает исключение. Я думаю, если я должен придерживаться стандарта throw new Exception или если я должен создать конкретные исключения.

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

Когда добавление пользовательского исключения не так полезно?

[EDIT]

Разделяя мои мысли, я думаю, что пользовательское исключение является обязательным(по крайней мере, одно) для компонента, поэтому при модульном тестировании вашего собственного компонента вы не получите false позитивы.

Это приводит к ложным срабатываниям:

[Test]
public void Tag_is_missing()
{

    string message = "";

    try
    {
        // Arrange  
            // this will fail on *nix systems       
        MyComponentHelper.ParseXml("C:A.XML");
    }
    catch(Exception ex)
    {
        // Act
        message = ex.InnerException.Message;
    }


    // Assert
    // How can we be sure that the word "not found" error is from 
    // xml parsing or if from file loading? Doing Pokemon exception handling
    // will lead to ambiguities
    Assert.IsTrue(message.Contains("not found"));

}

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

Это не приведет к ложным срабатываниям:

[Test]
public void Tag_is_missing()
{

    string message = "";

    try
    {
        // Arrange     
        // this will fail on *nix systems        
        MyComponentHelper.ParseXml("C:A.XML");
    }
    catch(XmlParsingException ex)
    {
        // Act
        message = ex.InnerException.Message;

        // Assert
        // And now we are more sure that the error didn't come from
        // program subsystem; in particular, file subsystem.
        Assert.IsTrue(message.Contains("not found"));
    }


}

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

3 2

3 ответа:

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

Пользовательское исключение - это только оболочка вокруг системного исключения. Исходная информация об исключении находится в свойстве InnerException пользовательского исключения.

Класс исключений может быть выполнен в виде:


public class NewException : BaseException, ISerializable
{
    public NewException()
    {
        // Add implementation.
    }
    public NewException(string message)
    {
        // Add implementation.
    }
    public NewException(string message, Exception inner)
    {
        // Add implementation.
    }

    // This constructor is needed for serialization.
   protected NewException(SerializationInfo info, StreamingContext context)
   {
        // Add implementation.
   }
}

При создании пользовательского исключения используйте:


try
{
   .....
}
catch(ArgumentNullException argumentNullException)
{
   throw new NewException("This is a custom exception message", argumentNullException);
}

Кроме того, рекомендуется перехватывать базовый System.Exception только в самом верхнем классе элементов управления. Во внутренних классах следует перехватывать определенные типы исключений и при необходимости использовать пользовательские исключения.

Для получения дополнительной информации см.:

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

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

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

Также имейте в виду, что Исключения делаются для исключительных случаев. имеет ли смысл создавать исключение, или вам лучше будет вернуть некоторое значение (я не имею в виду код ошибки)?