我正在从 php 中的普通 mysql 切换到 PDO,我注意到测试错误的常用方法是使用 try / catch 组合而不是 if / else 组合。
该方法的优点是什么,我可以使用一个 try / catch 块而不是几个嵌套的 if / else 块来处理不同步骤(连接、准备、执行等)的所有错误吗?
当通过代码的正常路径应该没有错误地进行时,我会使用 try/catch 块,除非确实存在一些异常情况——比如服务器关闭、您的凭据过期或不正确。我不一定会用它来处理非异常错误——比如当前用户没有扮演正确的角色。也就是说,当您可以合理地预期并处理不是异常情况的错误时,我认为您应该进行检查。
在您所描述的情况下——设置和执行查询,try/catch 块是处理它的好方法,因为您通常期望查询成功。另一方面,您可能希望检查结果的内容是否符合您对控制流逻辑的期望,而不是仅仅尝试使用可能对您的目的无效的数据。
您要注意的一件事是草率地使用 try/catch。Try/catch 不应该用来保护自己免受不良编程的影响——“我不知道如果我这样做会发生什么,所以我将把它包装在 try/catch 中并希望最好的”类型的编程。通常,您会希望将捕获的异常类型限制为与代码本身无关的异常(服务器停机、错误凭据等),以便您可以找到并修复与代码相关的错误(空指针等) .)。
一般来说,try-catch 块很棒,因为只要发生异常,它们就会中断(移动到 catch 语句)。If-else 块依赖于您预测错误何时发生。
编辑:此外,当遇到错误时,catch 块不会阻止您的代码停止。
try/catch 和一般异常的优势更多地适用于开发像 PDO 这样的库的人。它们允许系统开发人员以快速简单的方式处理未定义的情况或意外结果。建立数据库连接。如果无法访问数据库,系统应该怎么做。它应该停止执行吗?再试一次?发出警告并继续?系统开发人员不知道你需要它做什么,他们会抛出一个异常,你稍后会捕获并处理它。
对您来说,作为系统的消费者,您的优势不是得到一些模糊的错误代码,或者是一个简单的布尔错误,它失败了,你得到一个异常对象,它将
以这样的方式命名,以便更明显地出错(如果我没记错的话,PDO 只有一种异常类型,但其他系统包含多种异常类型,用于不同类型的错误)
可能/应该包含可以帮助您找出引发异常的原因的方法和属性
无论如何,这就是理论。有很多聪明人声称例外是要走的路。也有很多聪明人认为异常是魔鬼,是懒惰的系统开发者的拐杖。在这个问题上没有任何类似的共识。
与大多数其他原始操作相比,抛出和捕获异常是一项昂贵的操作。如果这是一段需要良好执行的代码(例如,在一个紧密的循环中),您将需要查看您的用例 - 如果您希望相对频繁地抛出异常,那么使用 if 会更好/else 性能方面(除非底层代码只是为您包装了一个异常,在这种情况下根本没有任何收益)。如果仅在极少数情况下抛出异常,那么最好使用 try/catch 以避免在紧密循环中分支的开销。
@Perchik:
我的错误处理的一般理念:
您应该使用 if / else 来处理您期望的所有情况。您不应该使用try {} catch {} 来处理所有事情(在大多数情况下),因为可能会引发有用的异常,并且您可以从中了解是否存在错误。在您怀疑某些事情可能/将会出错并且您不希望它导致整个系统崩溃的情况下,您应该使用 try {} catch {},例如网络超时/文件系统访问问题、文件不存在等.
Try/Catch 将错误处理逻辑与对象业务逻辑完全分离。
这正是优势,使用一个 try/catch 而不是多个 if 语句。您还可以捕获任何未预料到的错误。
其他人都有很好的答案——但我想我会自己回答:
由于 PDO 正在使用对象,因此如果发生错误,它们会引发异常。旧的 mysql/mysqli 只是函数,不会抛出异常,它们只是返回错误代码。当可以从代码中抛出异常时使用 Try/catch,并且您在 catch 子句中捕获它,这是一种处理错误的面向对象的方式。你不能用 if/else 块捕获异常——它们与 try/catch 没有任何共享。
在php中通过使用带有继承的Try Catch,我们可以从另一个类中抛出异常。
示例:-我正在使用controller
并验证用户数据Models
。
如果触发任何错误,我只需要从Model
方法中抛出异常。
try 中的执行将中断并在Catch
Block 中捕获。
所以返回布尔值和检查的开销更少。
除此之外,在链中(在另一个内部)Try Catch
使用时效果很好。Try - Catch
Try - Catch
十多年前,这个问题就在错误的前提下被提出。实际上,如果和尝试是无法比拟的。可悲的是,但直到今天,人们灾难性地将异常与try catch混淆,认为一个与另一个密不可分。
在询问的方式中,实际上将 if {} 更改为 try {} 的意义在于强制尝试包装一行代码以测试错误。
然而,实际的问题是使用异常与 if {} else {} 相比有什么优势。
并且它立即开始变得有意义:异常允许自动错误报告,此时既不需要编写 try catch 也不需要编写 if else。
异常本质上是一种自动化的编写方式,if ($result == FALSE) raise_error();
如果没有异常,您必须手动测试每个操作的结果。使用异常重新创建相同的行为只是愚蠢的。在大多数情况下,应该不理会抛出的异常,除非有特定的处理场景。在所有其他情况下,它必须在其他地方冒泡,因此不必编写 try {} catch {}。
假设我们正在编写一个 a/b 除法代码,并且发生了最著名的异常情况,即 0 除法错误,您认为接下来可以做什么?1.您可以打印一条消息并退出。2.您可以打印一条消息并让用户重新输入值等。
在某些情况下,不同的人/供应商希望以不同的方式处理相同的异常情况。catch块让他们轻松地做到这一点。如果您需要更改处理某个异常情况的方式,您只需要更改 catch 块。
TRY/CATCH 可以在您对错误信息很少或您认为可能会发生的编程上下文中使用,例如。
#include <iostream>
using namespace std;
int main (){
try{
while(true){
new int[100000];
}
}
catch(bad_alloc& e){
cout << e.what() << endl;
}
}
虽然程序中没有语义或编译时错误,但可以理解的是,当您尝试连续分配内存并且程序耗尽内存时,它会出现“bad_alloc”的运行时错误。这个异常定义在 bad_alloc 标准类中,它是类“Exception”的子类,因为它抛出一个隐式异常,所以这里没有隐含 throw 关键字。
也可以使用 try/catch 来检查文件是否被误删除,也可以使用 if/else 来检查文件是否存在,两者各有优势。
当函数之间存在通信时,Try 和 Catch 函数很有用。在 Try 和 Catch 中,如果 TRY 块中存在异常,则控制将直接转移到 CATCH 块,该块将存储我们的异常条件。然而,这在 IF ELSE 的情况下是不可能的,在 IF 条件下,如果存在异常,无论如何控制都不能转到 ELSE 块。
int division(int a,int b){
if(b==0)
throw 101;
return a/b;
}
int main()
{
int a=10,b=0,c;
try{
c=division(a,b);
cout<<c<<endl;
}
catch(int a){
cout<<"Division not possible by 0"<<endl;
}
}
考虑以下代码: throw 和 catch 函数用于函数划分和主函数之间的通信。请注意,当 b 为 0 时,不执行打印 c 的语句,因为在抛出值 os 后,控件直接转移到 catch 块。然而,如果这里是 IF ELSE,这是不可能的。