首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么是异常,为什么要“抛出”它们?

什么是异常,为什么要“抛出”它们?
EN

Stack Overflow用户
提问于 2017-04-12 21:44:44
回答 3查看 421关注 0票数 0

我在StackOverflow上读过许多站点和其他响应,但我仍然没有理解异常处理的重要性以及我们为什么“抛出”它们。

对于这篇文章,我对一个例外的理解可以最好地描述为:

“异常是程序执行过程中出现的问题。C#异常是对程序运行过程中出现的异常情况的响应……”handling.htm

在处理异常时,我经常看到以下代码片段:

代码语言:javascript
运行
复制
try 
{
    // Do something that causes an Exception
}
catch (Exception)
{
    // Could have error logging here
    throw;
}

如果您没有执行任何错误日志记录,为什么有"try/catch“和”not“语句?不管我是否尝试/捕获,代码仍然会抛出一个异常。我一定是漏掉了什么。“扔”是干什么的?

我在以下内容中包含了一个基本除以零的场景:https://repl.it/BjgV/24。当您删除“尝试/捕捉/抛出”时,您会看到相同的结果。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-04-12 22:21:38

要记住的是,捕获的异常不仅可以用于日志记录错误,还可以用于处理可能出现的错误。

假设您有某种Widget对象,它具有通过构造函数的参数初始化的属性:

代码语言:javascript
运行
复制
public class Widget
{
    public string Name;

    Widget(string widgetName)
    {
        if (widgetName != "")
            Name = widgetName;
        else
            throw new ArgumentException("Name must be provided for widget.");
    }
}

在这种情况下,我们希望在实例化时要求我们的Widget有一个名称--我们检查参数以查看它是否为空,然后抛出一个,以表明构造函数的一个参数有问题,并包含了一条关于具体出错的有用消息。

这意味着我们可以在包装器中使用特定于上下文的验证逻辑,而不必将所有内容都塞进基本的Widget类中:

代码语言:javascript
运行
复制
public Widget ForCaseA (string widgetName) 
{
    Widget w;

    try {
        w = new Widget(widgetname);
    }

    catch (ArgumentException as argEx) // We're specifically catching the subtype of ArgumentExceptions; generic Exceptions or other types of exception wouldn't be caught here and would bubble up out of this try/catch block.
    {
// At this point, we could look at the specific data in the exception object to determine what needs to happen to resolve the exception. Since there's only one argument and it's throwing an ArgumentException, we know it's going to be a problem with a bad widgetName. In this case, we can say 'well, in this specific case, we want to give it a default widget name'.
        w = new Widget("DefaultName");
    }

    return w;
}

按类型捕获异常的一种方法非常有用:当您使用继承创建基于泛型异常类的自己的类型时,例如给您的小部件一个这允许您捕获特定于您的类/实体的问题(比如小部件的名称),但不需要处理超出Widget本身范围的问题。

票数 1
EN

Stack Overflow用户

发布于 2017-04-12 21:50:45

“抛出”有时(在非oop语言中)与“引发”错误相同。

如果我们捕捉到一个异常,我们可能希望在调用堆栈中的某个较高的方法中将其冒泡,并在此过程中对其进行更多的概括。因此,我们可以使用如下内容:

代码语言:javascript
运行
复制
try { doSomething(); } 
catch (VerySpecificException ex) {
    throw new SomeGenericException(ex);
}

这允许我们在高级编程中只期望通用异常,同时维护完整的堆栈跟踪和内部异常,这样我们就可以看到它来自何处。

抛出本身(如在您的示例中),只需将错误推送到下一个调用方,而不进行任何更改。在您的确切示例中,您可能完全忽略了try/catch,因为结果是一样的(异常被推到下一个块:例外可能是如果您有一些AOP或者在其中编织来处理它,但我认为这个答案有点超出了这个答案)。

如果没有try/catch块,则将异常推后到调用堆栈中的下一个方法。如果在任何地方都没有try/catch块,则该异常被称为“未处理”,您的应用程序就会崩溃。没有任何理由让一个未经处理的例外能够达到顶峰。

票数 1
EN

Stack Overflow用户

发布于 2017-04-12 21:57:33

特别是关于这一部分:

如果您没有执行任何错误日志记录,为什么有"try/catch“和”not“语句?

除了记录异常之外,在某些情况下,您可能希望:

  • 将异常包装在有意义的用户定义异常中,您将抛出该异常以引发某些错误。
  • 释放某些资源,以防出现异常,并将其泡沫起来,以便在其他地方进行可能的处理。

这只是两个例子。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43380157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档