我正在从php中的普通mysql切换到PDO,我注意到测试错误的常用方法是使用try / catch组合而不是if / else组合。
该方法的优点是什么,我可以使用一个try / catch块而不是几个嵌套的if / else块来处理不同步骤(连接,准备,执行等)的所有错误吗?
答案 0 :(得分:52)
当通过代码的正常路径应该没有错误时,我会使用try / catch块,除非确实存在一些异常情况 - 例如服务器关闭,您的凭据已过期或不正确。我不一定会用它来处理非异常错误 - 比如当前用户没有正确的角色。也就是说,当你可以合理地期望并处理一个非特殊情况的错误时,我认为你应该做你的检查。
在您描述的情况下 - 设置和执行查询,try / catch块是处理它的绝佳方式,因为您通常希望查询成功。另一方面,您可能希望检查结果的内容是否符合您对控制流逻辑的期望,而不是仅仅尝试使用可能对您的目的无效的数据。
您想要注意的一件事是使用try / catch。 Try / catch不应该被用来保护自己免受糟糕的编程 - “我不知道如果我这样做将会发生什么,所以我将把它包装在try / catch中并希望获得最好的”编程。通常,您需要将捕获的异常类型限制为与代码本身无关的异常(服务器关闭,错误凭据等),以便您可以找到并修复与代码相关的错误(空指针等) )。
答案 1 :(得分:15)
通常,try-catch块很棒,因为每当异常发生时它们都会中断(移动到catch语句)。 If-else块依赖于您预测错误何时发生。
编辑: 此外,catch块不会阻止代码在发生错误时停止。
答案 2 :(得分:7)
Try / Catch将错误处理逻辑与对象业务逻辑完全分开。
答案 3 :(得分:7)
try / catch的优势以及一般的例外情况更适用于像PDO这样的人开发库。它们允许系统开发人员以快速简便的方式处理未定义的情况或意外结果。进行数据库连接。如果无法访问数据库,系统应该应该做什么。它应该停止执行吗?再试一次?发出警告并继续?系统开发人员无法知道你需要做什么,他们会抛出异常,你以后会抓到并处理它。
作为系统的消费者,您的优势不是获得一些模糊的错误代码,或者是一个简单的布尔值假失败,您将得到一个Exception对象
以这样的方式命名,以便更明显出错(如果我没记错的话,PDO只有一个Exception类型,但其他系统包含多种异常类型,用于不同类型的错误)
< / LI>可能/应该包含的方法和属性可以帮助您找出为什么抛出异常
无论如何,这就是理论。有很多聪明的人声称例外是可行的方法。还有很多聪明的人认为Exceptions是魔鬼,也是懒惰系统开发人员的拐杖。在这个问题上没有任何类似的共识。
答案 4 :(得分:6)
与大多数其他原始操作相比,抛出和捕获异常是一项昂贵的操作。如果这是一段需要运行良好的代码(例如,在紧密的循环中),您将需要查看您的用例 - 如果您希望相对经常抛出异常,那么最好使用if / else perforance-wise(除非底层代码只是为你包装一个例外,在这种情况下根本没有任何收益)。如果仅在极少数情况下抛出异常,那么最好使用try / catch来避免在紧密循环中分支的开销。
答案 5 :(得分:5)
这正是优势,使用一个try / catch而不是多个if语句。您还可以捕获任何意料之外的错误。
答案 6 :(得分:5)
@Perchik:
我的错误处理的一般哲学:
你应该使用if / else来处理你期望的所有情况。您应该不使用try {} catch {}来处理所有内容(在大多数情况下),因为可以引发一个有用的Exception,您可以从中了解bug的存在它。在怀疑某些事情可能/会出错的情况下,你应该使用try {} catch {}并且你不希望它导致整个系统崩溃,例如网络超时/文件系统访问问题,文件不存在等等。
答案 7 :(得分:3)
由于PDO正在使用对象,因此如果发生错误,它们会引发异常。旧的mysql / mysqli仅仅是函数,并没有抛出异常,只是返回错误代码。当可以从代码中抛出异常时使用Try / catch,并在catch子句中捕获它,这是一种面向对象的方法来处理错误。你不能用if / else块来捕获异常 - 它们与try / catch没有共享。
答案 8 :(得分:3)
其他人都有很好的答案 - 但我想我会自己投入:
答案 9 :(得分:2)
在php中使用带有继承的Try Catch,我们可以从另一个类中抛出异常。
示例: - 我在controller
并使用Models
验证用户数据。
如果发生任何错误,我只需要从Model
方法中抛出异常。
try中的执行将在Catch
Block中断开并捕获。
因此返回bool值并检查它的开销较少。
除此之外Try Catch
效果很好在链中使用(Try - Catch
在另一个Try - Catch
内)。
答案 10 :(得分:1)
完全同意@Jared Updike
通常,异常处理是在用户知道很少或根本不知道的情况下完成的。另一方面,系统的用户知道if-else块内发生了什么。
例如。它应该是一个显示ATM用户的“else”子句,当他的余额很低时,消息“银行余额不足”。并且这条消息不能出于任何原因坐在“捕获”区块内!
答案 11 :(得分:1)
这个问题是十多年前出于错误前提提出的。实际上,if和try是无与伦比的事情。令人遗憾的是,但是直到今天,人们仍然灾难性地将例外与 try catch 混为一谈,认为一个人与另一个人密不可分。
按照要求,实际上{{}尝试{}来更改实际上没有什么意义,这意味着必须尝试包装一行代码来测试错误。
但是实际问题是使用例外和{} else {}相比有什么好处。
它立即开始使人们大开眼界:无需尝试捕获或无需编写时,例外允许自动错误报告。
从本质上说,异常是一种自动写入if ($result == FALSE) raise_error();
的自动化方式。没有异常,您就必须手动测试每个操作的结果。使用异常重新创建相同的行为只是愚蠢的。在大多数情况下,除非有某种处理方案,否则应将抛出的异常搁置一旁。在所有其他情况下,它必须在其他地方冒泡,因此无需尝试{} catch {}。
答案 12 :(得分:0)
假设我们正在编写a / b划分代码,并且发生了最著名的异常情况,即0划分错误,那么您认为下一步可以做什么? 1.您可以打印一条消息并退出。 2.您可以打印一条消息,然后让用户重新输入值,等等。
在某些情况下,不同的人员/供应商希望以不同的方式处理同一例外情况。 catch 块使他们可以轻松地执行此操作。如果您需要更改处理特定异常情况的方式,则只需更改catch块。
答案 13 :(得分:-1)
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来检查文件是否存在,两者都有其自身的优势。
答案 14 :(得分:-2)
Try和Catch函数在函数之间进行通信时很有用。在Try and 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 and catch函数用于函数划分与主函数之间的通信。 请注意,当b为0时,不会执行打印c的语句,因为在抛出os值之后,控件直接转移到catch块。 但是,如果在这里是ELSE的话,这是不可能的。