2

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

我还认为用户定义的异常在从 Remoting 或 WCF 引发异常时没有吸引力。如果我使用标准异常,调用者可以接收到异常,如果我做了一个用户定义的异常,调用者将无法接收到特定的异常,除非组件的程序集也部署到客户端;但是,如果从 Remoting 和 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"));
    }


}

剩下要思考的是何时应该创建非常具体的用户定义异常。现在,我将首先确定我的组件只有一个用户定义的异常,单元测试不应该产生误报。

4

3 回答 3

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仅在最顶层的控制类中捕获基类。在内部类中,您应该捕获特定的异常类型并在需要时使用自定义异常。

欲了解更多信息,请参阅:

于 2010-12-28T02:24:53.940 回答
0

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

于 2010-12-28T01:32:05.320 回答
0

捕获异常是非常通用的,并且可以通过组件的其他区域掩盖其他意外错误(如您所提到的)。使用属性或其他消息是一种选择。

但是,我发现最有效的方法是抛出一个标准异常,它是 Exception 的子类(例如 ArgumentOutOfRangeException);如果这些不够精确,并且您需要扔东西,请创建一个子类并扔掉它。

还要记住,例外是针对特殊情况的。抛出异常是否有意义,或者通过返回一些值(我不是指错误代码)会更好地为您服务?

于 2010-12-28T02:33:07.350 回答