什么时候最好不要创建用户定义的异常?

时间:2010-12-28 01:26:45

标签: c# exception custom-exceptions

我制作了一个抛出异常的组件。我在想是否应该坚持标准throw new Exception或者我是否应该创建特定的例外。

我还认为用户定义的异常在从Remoting或WCF抛出异常时没有吸引力。如果我使用标准异常,调用者可以接收异常,如果我做了一个用户定义的异常,调用者将无法接收特定异常,除非组件的程序集也部署到客户端;但是,如果从远程处理和WCF中捕获用户定义的异常,客户端可以从用户定义的异常中接收异常,并将其重新抛出为标准异常,这反过来会破坏用户定义异常的目的。

何时添加用户定义的异常不太有用?

[编辑]

分享我的想法,我认为用户定义的异常是组件必须(至少一个),因此当您对自己的组件进行单元测试时,您将不会收到误报。

这会产生误报:

[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 个答案:

答案 0 :(得分:2)

当您认为标准异常(由.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。在内部类中,您应该捕获特定的异常类型,并在需要时使用自定义异常。

有关更多信息,请参阅:

答案 1 :(得分:0)

我认为用户定义的异常只有在内部项目开发中以良好的方式解决您的问题才有意义。

答案 2 :(得分:0)

Trapping for Exception非常通用,可能会掩盖组件其他区域的其他意外错误(如您所述)。使用属性或其他消息是一种选择。

然而,我发现最好的方法是抛出一个标准异常,它是Exception的子类(例如ArgumentOutOfRangeException);如果那些不够精确,你需要抛出一些东西,做一个子类并扔掉它。

另请注意,例外情况适用于特殊情况。抛出异常是否有意义,或者通过返回一些值来更好地服务(我不是指错误代码) ?