Exception D语言中的惯用错误处理
我试图找到关于处理错误的标准化和公认的惯用D方式的资源,但我找不到任何。如果你正在阅读官方文件,那么你会发现以下非常重要的陈述:Exception D语言中的惯用错误处理,exception,error-handling,scope,d,Exception,Error Handling,Scope,D,我试图找到关于处理错误的标准化和公认的惯用D方式的资源,但我找不到任何。如果你正在阅读官方文件,那么你会发现以下非常重要的陈述: 错误不是程序正常流程的一部分。错误是异常的、不寻常的和意外的 因为错误是不寻常的,所以执行错误处理代码并不是性能关键 程序逻辑的正常流程对性能至关重要 我把它们称为重要的,因为对这种,嗯,例外情况使用例外的推理是导致本文得出结论的原因,错误毕竟是特殊情况,例外是要走的路,不管代价是什么。同样来自同一篇文章: 因为错误是不寻常的,所以执行错误处理代码并不是性能关键。
- 错误不是程序正常流程的一部分。错误是异常的、不寻常的和意外的
- 因为错误是不寻常的,所以执行错误处理代码并不是性能关键
- 程序逻辑的正常流程对性能至关重要
那么,处理D中不是异常的错误的正确和惯用的方法是什么呢?好的,TLDR版本是使用异常是处理D中错误条件的惯用方法,但当然,细节要比这复杂一些 问题的一部分是什么构成了错误。“错误”一词用于很多事情,因此,谈论错误可能会让人非常困惑。有些类错误是编程错误(因此是程序错误的结果),其他类错误不是编程错误,但灾难性严重,程序无法继续,其他类错误依赖于用户输入等内容,通常可以从中恢复 对于编程错误和灾难性错误,D有
Error
类,该类派生自Throwable
。Error
的两个常用子类是AssertError
和RangeError
-AssertError
是断言失败的结果,而RangeError
是尝试使用超出范围的索引对数组进行索引时得到的结果。这两个都是程序错误;它们是程序中错误的结果,从中恢复是没有意义的,因为根据定义,此时程序处于无效状态。一个不是bug但通常灾难性足以导致程序终止的错误示例是MemoryError
,当new
无法分配内存时抛出该错误
当抛出错误
时,不能保证任何清理代码都会运行(例如,可以跳过析构函数和scope
语句,因为假设您的代码处于无效状态,清理代码实际上可能会使事情变得更糟)。程序只需展开堆栈,打印出错误的消息和堆栈跟踪,然后终止程序。因此,试图捕捉一个错误
并让程序继续运行几乎总是一个糟糕的想法,因为程序处于未知和无效状态。如果某个东西被认为是一个错误
,那么它就是那种错误情况被认为是不可恢复的,程序不应该试图从中恢复
在大多数情况下,您可能不会对Error
s执行任何显式操作。当不使用-release编译时,您将在代码中放置断言以捕获bug,但您可能不会显式抛出任何错误。它们主要是D的运行时或您正在运行的代码中的断言捕获程序中的错误的结果
另一个从Throwable
派生的类是Exception
。它用于以下情况:问题不是程序中的错误,而是由于用户输入或环境造成的问题(例如,用户提供的XML无效,或者程序试图打开的文件不存在)。异常为函数提供了一种报告其输入无效或由于无法控制的问题而无法完成任务的方法。然后,程序可以选择捕获该异常
并尝试从中恢复,也可以让它冒泡到顶部并杀死程序(尽管通常,捕获它们并打印出比带有堆栈跟踪的消息更用户友好的内容更用户友好)。与错误
s不同,异常
s会导致所有CLE
int isDir(string filename, ref bool result);
if(file.isDir)
{
...
}
bool result;
immutable error = file.isDir(result);
if(error != 0)
{
...
}
else if(result)
{
...
}