如何决定使用if / else vs try / catch?

在编写代码时,如何决定使用if / else还是try / catch? 例如,在检查文件时,这应该基于if / else(if(File.Exists))还是try / catch块?

例如,可以通过if / else块处理写入文件以创建文件然后写入文件,或者假设文件存在而尝试/ catch。 选择有哪些注意事项?

谢谢

你永远不应该使用try / catch进行流量控制。

生成exception是一项非常昂贵的操作。 如果/ else更快更清洁。

在处理文件时,应始终使用try / catch,因为文件的状态可能会在程序之外发生变化。

请考虑以下代码位:

if(File.Exists("file.txt")) File.Delete("file.txt") 

Delete()调用之前,if语句之后的另一个进程可能已删除该文件。 当您尝试删除它时,会引发exception。

在处理文件时,还有许多事情要考虑,您可能无法捕获ifs,例如文件位于不可用的网络连接,更改的访问权限,硬盘故障等。

这些东西超出了程序的控制范围,所以你应该有exception处理程序。

如果您认为操作通常应该成功,那么try/catch可以更容易阅读。 特别是,如果有许多失败的原因(多个catch块)。

否则,如果它有时成功并且有时失败 – 并且由于特定原因这样做,则使用if/else (这称为结构化exception处理)。

有些人指出如何使用try/catch进行exception处理非常耗时。 我倾向于按照以下方式阅读类似的建议:如果您的分析表明存在性能问题,请不要在紧密的内循环中执行此操作。 在编写初稿时,不要考虑在这个级别进行优化!

当出现意外情况(exception)并且你想对它做一些特别的事情时,你可以使用try / catch,例如:

 try { //Do something that might rise an exception, say a division by 0 //this is just an easy example as you might want to check if said value is not 0 //before dividing int result = someNumberOfMine / anUnsafeNumber; } catch { //if something unexpected happened, do a special treament } 

在您的特定情况下,我建议使用File.Exists来validation文件的存在而不是使用try / catch块,因为在使用它之前可以检查文件是否存在。

只是为了让话题得到rest(是的,这个问题是在8个月之前提出的,但互联网总是知道!),我决定进行一些测试, 如果你很确定你没有exception – 例如,“else”部分仅在0.001%的时间内发生。 事实certificate,如果您永远不必捕获/其他任何东西,那么try-catch大约快4%(在我的机器上,无论如何)。 这是代码和附带的结果:

案例1:if-else:

 var startTime = DateTime.Now; int bazillion = 100000000; int[] list = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; for (int i = 0; i < bazillion; i++) { for (int k = 0; k < list.Length; k++) { if (k >= 0) { list[k] = i; } else { // do nothing. } } } var executionTime = DateTime.Now - startTime; Debug.WriteLine (executionTime.TotalMilliseconds); 

5次运行的执行时间(毫秒):7441.4256,7392.4228,7545.4316,7531.4308,7323.4188。
平均值= 7446.82592毫秒

案例2:try-catch:

 var startTime = DateTime.Now; int bazillion = 100000000; int[] list = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; for (int i = 0; i < bazillion; i++) { for (int k = 0; k < list.Length; k++) { try { list[k] = i; } catch (Exception e) { // do nothing } } } var executionTime = DateTime.Now - startTime; Debug.WriteLine(executionTime.TotalMilliseconds); 

5次运行的执行时间(毫秒):7258.4152,7137.4083,7070.4044,7052.4033,7120.4073平均值= 7127.8077毫秒

结论 (基于这个相当简单的例子;实际里程可能会有所不同等)
就纯粹的数字而言, 如果您确定不会发生exception/ else情况,则try-catch比每次执行“if”子句快4%。

只有在特殊情况下才能进行特殊处理。

在依赖于文件是否存在的情况下,只使用try catch块就没有意义

 if(File.Exists(path)) { } else { } 

exception处理会导致很多性能File.Exists(path))因此请尝试通过在代码中应用更多检查来最小化exception情况,例如File.Exists(path))

一般来说,这取决于

对于基于文件的东西,你几乎总是想尝试操作并处理失败而不是先检查。 原因是文件系统是共享资源,并且您不能保证在file.exists返回true之后文件确实存在,因为其他进程可能同时删除了它。

正如一些答案已经指出的那样,这取决于。

如果/ else用于流控制,那么可以使用添加的正例来捕获发生的错误。 但是,正如Turowicz所指出的那样,对于很多人来说这被认为是不好的做法,使用try / catch超过你所需要的最小值。

您可以随时阅读Ned Batchelder的这些文章(关于返回代码的谈话,作为使用exception的替代方法)和Joel Spolsky (为什么他不喜欢使用例外编程)来了解其他人对exception的看法然后让你的自己的想法。

只是一个想法…其中一个答案是你应该尝试捕获,例如,如果你有零除可能性。 我想知道为什么? 你掌握在这里,你可以在分裂之前进行检查,并采取行动。 如果它为零,则您不需要进行除法,而是执行另一个逻辑。

我只会在你无法控制或不能(或没有意义)事先检查事物(打开文件,……)的情况下使用try catch。

在你的情况下,我会使用File.Exists和try / catch。 File.Exists作为业务检查(不需要在不存在时打开它),try / catch来捕获打开文件时可能发生的任何exception。

当预期文件不存在时,首先检查是否存在。 但是当丢失的文件是一个不寻常的状态时,你应该指出这个exception状态并带有exception。

所以基本的想法是:尽量避免在可预期的情况下出现exception。

一般来说,你应该做两件事 try / catch以避免exception情况(文件突然从另一个线程中删除)。 如果/ else处理非exception(检查文件是否存在)。 Try / catch比通常的if / else慢,所以不值得将它用于所有东西。

在做出这些决定时,“例外应该是例外”的格言很有用。 主要是您应该使用标准程序流(即if语句)处理已知情况,以便exception表示意外情况(即错误)。

当然,就像任何规则一样,它会被打破。

另外,我不会太担心exception处理对性能的影响。 除极端情况外,开销几乎可以忽略不计。

为此您知道文件退出问题。 所以你更喜欢别的。

如果您不知道问题,最好使用try catch。

我建议两者,如下所示

 try { if(File.Exists(path)) { do work } else { messagebox.show("File Path Not Exit"); } } catch(Exception e) { messagebox.show(e); } 

它捕获了我们没有想到的所有错误。

从所有答案中可以明显看出,没有标准/批准的方式来决定是否应该使用其中一种。 如果操作正确,两种方法都将有效。 如果操作不正确,两种方法都会效率低下。

我更喜欢if / else语句,当它有意义时(即在我自己的函数中)和Try语句,当我调用函数时我无法控制。

在上面的例子中,如果您控制文件(意味着没有其他程序可能操纵它),File.Exists()就足够了,但如果文件在检查和使用之间有可能消失则不够。

根据我的经验,在大多数情况下,文件操作通常可以更好地处理exception,因为在c#中这些非常大的文件操作会引发exception。 它们不返回可以使用if语句检查的错误代码。