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

发布于 2024-10-09 01:30:39 字数 1692 浏览 8 评论 0原文

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

我还认为,当用户定义的异常从 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"));
    }


}

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

I have made a component that throws Exception. I'm thinking if I should stick with standard throw new Exception or if I should create specific exceptions.

I also consider user-defined exception as not appealing when it throws exception from Remoting or WCF. if I use standard exception, the caller can receive the exception, if I made a user-defined exception, the caller won't be able to receive the specific exception unless the component's assembly is also deployed to client; however, the client can receive the exception from user-defined exceptions if one catches the user-defined exception from within Remoting and WCF and rethrows it as standard exception, which in turn defeats the purpose of user-defined exception.

When is adding user-defined exception not so useful?

[EDIT]

Sharing my thoughts, I think user-defined exception is a must(at least one) on a component, so when you unit test your own component, you will not receive false positives.

This produces false positives:

[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"));

}

If you didn't made your own exception, your unit test might receive false positives, the "not found" string could be from your component or from other subsystems of your component. So there goes my case of when one should create user-defined exception.

This won't produce false positives:

[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"));
    }


}

What's left to ponder is when one should create very specific user-defined exceptions. For now, I'll settle first on having just one user-defined exception for my component, unit testings should not yield false positives.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

物价感观 2024-10-16 01:30:39

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

有关详细信息,请参阅:

Use custom exceptions when you feel that the standard exceptions (provided by .NET) do not give enough information about the exception condition. In this custom exception, you could provide properties that provide more information about the exception than just the message string.

The custom exception is only a wrapper around the system exception. The original exception information is found in the InnerException property of the custom exception.

The exception class can be designed as:


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.
   }
}

While throwing the custom exception, use:


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

Additionally, it is recommended that you catch the base System.Exception only in the top most control class. In the inner classes you should catch the specific exception types and use custom exception if required.

For more information refer:

小伙你站住 2024-10-16 01:30:39

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

I think user-defined exceptions have only sense when this solve your problem in good way in internal project development.

格子衫的從容 2024-10-16 01:30:39

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

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

另请记住,异常是针对特殊情况的。抛出异常是否有意义,或者返回一些值(我不是指错误代码)会更好吗?

Trapping for Exception is very generic, and could mask other unanticipated errors (as you've mentioned) by other areas of your component. Using properties or other messages is an option.

However, the approach that I've found works best is to throw one of the standard exceptions that's a subclass of Exception (eg. ArgumentOutOfRangeException); if those are not precise enough, and you need to throw something, make a subclass and throw that.

Also bear in mind that exceptions are for exceptional cases. Does it make sense to throw an exception, or would you be better served by returning some value (I don't mean an error code)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文