异常抛出:是否封装它们?

发布于 2024-09-04 16:14:21 字数 1053 浏览 3 评论 0原文

有一次我阅读了 MSDN 文章鼓励以下编程范式(它不是 100% 正确......请参阅编辑):

public class MyClass
{
    public void Method1()
    {
        NewCustomException();
    }

    public void Method2()
    {
        NewCustomException();
    }

    void NewCustomException()
    {
        throw new CustomException("Exception message");
    }
}

您认为这种范式有意义吗?将异常消息存储在 static const 字段中,然后将其传递给异常的构造函数,而不是封装整个异常抛出,这还不够吗?

编辑:

使用异常生成器方法。这是 一个类抛出相同的内容是很常见的 来自不同地方的异常 执行。为避免过度 代码,使用创建的辅助方法 异常并返回它。

我刚刚注意到(参见引文),文章告诉我们返回异常:

public class MyClass
{
    public void Method1()
    {
        throw NewCustomException();
    }

    public void Method2()
    {
        throw NewCustomException();
    }

    CustomException NewCustomException()
    {
        return new CustomException("Exception message");
    }
}

您对此有何看法?

Once I read an MSDN article that encouraged the following programming paradigm (its not 100% true... see edit):

public class MyClass
{
    public void Method1()
    {
        NewCustomException();
    }

    public void Method2()
    {
        NewCustomException();
    }

    void NewCustomException()
    {
        throw new CustomException("Exception message");
    }
}

Do you think this paradigm makes sense? Wouldn't it be enough to store the exception message in a static const field and then pass it to the exception's constructor, instead of encapsulating the whole exception throw?

EDIT:

Use exception builder methods. It is
common for a class to throw the same
exception from different places in its
implementation. To avoid excessive
code, use helper methods that create
the exception and return it.

I just noticed (see citation), that the article tells to return an exception:

public class MyClass
{
    public void Method1()
    {
        throw NewCustomException();
    }

    public void Method2()
    {
        throw NewCustomException();
    }

    CustomException NewCustomException()
    {
        return new CustomException("Exception message");
    }
}

What do you think about this?

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

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

发布评论

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

评论(7

灰色世界里的红玫瑰 2024-09-11 16:14:21

我的理解是,如果没有其他原因,除了丢失与异常相关的堆栈跟踪之外,传递异常实例是一种失礼行为。调用另一个方法会改变堆栈跟踪,从而使其变得毫无用处。我建议至少从异常中获取堆栈跟踪并将其作为参数传递给某个助手(如果这是您要走的路)。

My understanding is that passing an exception instance around is a faux pas if for no other reason than you lose the stack trace associated with the exception. Calling another method would change the stack trace and thereby make it effectively useless. I'd recommend at a minimum getting the stack trace off the exception and passing it as an argument to some helper if that's the road you're going to go down.

客…行舟 2024-09-11 16:14:21

在我的书中,这个重构太过分了。您必须返回堆栈跟踪中的一行才能准确查看问题发生的位置。如果您的自定义异常始终使用相同的消息,请将其放入 CustomException 类中。如果它仅在您引用的代码中相同,那么是的,将其放入 const 字段中(您不能使用 static const - 它隐式 静态)。

That's a refactor too far in my book. You have to go back up a line in the stack trace to see exactly where the problem occured. If your custom exception is always using the same message, put it in the CustomException class. If it's only the same within the code you've quoted, then yes, put it in a const field (you can't have static const - it's implicitly static).

一人独醉 2024-09-11 16:14:21

这样做的另一个问题是,在很多地方你甚至无法抛出异常,因为编译器不允许它。考虑将这两个方法添加到您的类中:

    public string GetFoo1(bool bar)
    {
        if (bar)
            return "";
        else
            NewCustomException();
    }

    public string GetFoo2(bool bar)
    {
        if (bar)
            return "";
        else
            throw new CustomException("Exception message");
    }

GetFoo1 不会编译,而 GetFoo2 可以。

Another problem you get doing that is that there will be lots of places where you wont even be able to throw an exception because the compiler wont allow it. Consider these two methods added to your class:

    public string GetFoo1(bool bar)
    {
        if (bar)
            return "";
        else
            NewCustomException();
    }

    public string GetFoo2(bool bar)
    {
        if (bar)
            return "";
        else
            throw new CustomException("Exception message");
    }

GetFoo1 will not compile while GetFoo2 will.

失眠症患者 2024-09-11 16:14:21

我想要一种构建异常的方法,而不是抛出异常的方法。如下面的示例所示。我似乎记得看到过推荐这样做的微软指南,但我不记得在哪里了。

使用这种技术,如果您出于任何原因想要更改异常类型,则只需在一个地方执行此操作(例如,在升级时从 ConfigurationException 更改为 ConfigurationErrorsException .NET 1.x 到 .NET 2.0)。

此外,您还可以通过使用构建异常及其消息和异常中包含的任何其他数据的代码的单个副本来尊重 DRY 原则。

您显然不会在微不足道的情况下执行此操作(例如,您不会将 throw new ArgumentNullException("myParamName") 替换为 throw BuildArgumentNullException("myParamName")

private static Exception BuildSomeException(... parameters with info to include in the exception ...)
{
    string message = String.Format(...);
    return new SomeException(message, ...);
}

...
throw BuildSomeException(...);

I would have a method that builds an Exception, rather than one that throws it. As in the sample below. I seem to remember seeing a Microsoft guideline that recommended this, but I can't remember where.

With this technique, if you want to change the exception type for any reason, you only need to do so in one place (e.g. a change from ConfigurationException to ConfigurationErrorsException when upgrading from .NET 1.x to .NET 2.0).

Also you respect the DRY principle by having a single copy of the code that builds the exception with its message and any other data included in the exception.

You obviously wouldn't do this in trivial cases (e.g. you wouldn't replace throw new ArgumentNullException("myParamName") by throw BuildArgumentNullException("myParamName"))

private static Exception BuildSomeException(... parameters with info to include in the exception ...)
{
    string message = String.Format(...);
    return new SomeException(message, ...);
}

...
throw BuildSomeException(...);
怀里藏娇 2024-09-11 16:14:21

我不认为创建一个简单地抛出异常的方法有什么意义。但是,我确实认为抛出自定义异常是有价值的。如果您抛出的所有异常都是自定义异常的子异常,那么您可以快速查看抛出的异常是您正在考虑的异常还是您尚未处理的异常。另外,您还可以捕获MyBaseException,而且它并不像捕获Exception那么糟糕。

I don't see the point of making a method that simply throws an exception. But, I do think trowing custom exceptions has value. If all of the exceptions you throw are children of a custom exception, it allows you to quickly see if the thrown exception is one you are accounting for or something you have not handled yet. Also, you can then catch MyBaseException and it is not as bad as catching Exception.

余生共白头 2024-09-11 16:14:21

如果您不知道计划如何准确地处理异常,那么这样做会很方便。你想直接扔掉它吗?或者也许稍后您将在某个地方记录异常然后抛出它?或者也许传递一些与异常捆绑在一起的参数(即方法名称等)?

在这种情况下,当您想要更改异常情况时,创建一个单独的方法来处理异常情况会很方便。

我通常不会为此烦恼 - 相反,只需预先弄清楚您将如何处理异常(即您将在消息中放入哪些字符串信息)。

It is handy to do this if you don't know how you plan to handle exceptions, exactly. Do you want to just throw it? Or perhaps later you are going to log the exception somewhere then throw it? Or maybe pass some arguments (i.e. method name, etc.) that get bundled in with the exception?

In this case, creating a separate method that handles the exception situation is convenient when you want to change it.

I don't usually bother with this - instead, just figure out upfront how you are going to handle exceptions (i.e. what string information you are going to putin the message).

許願樹丅啲祈禱 2024-09-11 16:14:21

我通常更喜欢将异常消息存储为资源。这有几个目的:

  • 如果要求归结为本地化异常消息,那么这是理所当然的。
  • 异常消息在开发人员之间往往更加标准化,因为创建新的但仅略有不同的消息需要额外的工作。
  • 如果您确保消息由标识符引用,并在抛出异常时包含该标识符,那么将消息跟踪到抛出该消息的代码会更容易。

缺点是它确实需要比硬编码消息稍微多一点的工作。

I generally prefer to store exception messages as resources. That serves several purposes:

  • If the requirement comes down to localize exception messages, it's a no-brainer.
  • Exception messages tend to be more standardized across developers since it's extra work to create a new, but only slightly different message.
  • If you ensure that messages are referenced by an identifier, and include the identifier with the exception when it's thrown, then tracing a message to the code that threw it is easier.

Downside is it does require (just) slightly more effort up front than hard-coding the messages.

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