编写代码时,如何决定使用if / else还是try / catch?例如,在检查文件时,这应该基于if / else(if(File.Exists))还是try / catch块?
例如,写入文件可以通过if / else块处理以创建文件然后写入文件,或者假设文件存在而尝试/捕获。选择有哪些注意事项?
由于
答案 0 :(得分:25)
你永远不应该使用try / catch进行流量控制。
生成异常是一项非常昂贵的操作。如果/ else更快更清洁。
答案 1 :(得分:17)
在处理文件时,应始终使用try / catch,因为文件的状态可能会在程序之外发生变化。
考虑以下代码位:
if(File.Exists("file.txt"))
File.Delete("file.txt")
在Delete()
调用之前,if语句之后的另一个进程可能已删除该文件。当您尝试删除它时,会引发异常。
在处理文件时,还有很多事情要考虑,你可能无法捕获ifs,例如文件位于不可用的网络连接上,访问权限发生变化,硬盘故障等
这些东西超出了程序的控制范围,所以你应该有异常处理程序。
答案 2 :(得分:9)
如果您认为该操作通常应该成功,那么try/catch
可以更容易阅读。特别是,如果失败的原因很多(多个catch
块)。
否则,如果它有时成功并且有时会失败 - 并且出于特定原因这样做,请使用if/else
(这称为结构化异常处理)。
有些人指出如何使用try/catch
进行异常处理非常耗时。我倾向于按照以下方式阅读类似的建议:如果您的分析表明存在性能问题,请不要在紧密的内循环中执行此操作。在编写初稿时,不要考虑在这个级别进行优化!
答案 3 :(得分:6)
只是为了让话题得到休息(是的,这个问题是8个月前提出的,但互联网总是知道!),我决定进行一些测试,效率更高 if 你很确定你不会有例外 - 例如,“其他”部分只会在0.001%的时间内发生。事实证明,如果你从不必须捕获/其他任何东西,那么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毫秒
结论 (基于此相当简单的示例;实际里程可能会有所不同等):
就纯粹的数字而言, if 你确定不会发生异常/ else情况,try-catch比每次执行“if”子句快4%左右
答案 4 :(得分:5)
当出现意外情况(异常)并且你想对它做一些特别的事情时,你可以使用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来验证文件是否存在,而不是使用try / catch块,因为在使用它之前可以检查文件是否存在。
答案 5 :(得分:4)
只有在特殊情况下才能进行或使用异常处理。
在一个依赖于文件是否存在的场景中,只有你可以使用try catch块是没有意义的
if(File.Exists(path))
{
}
else
{
}
异常处理会导致很多性能下降,因此请尝试通过在代码中应用更多检查来最小化异常情况,例如File.Exists(path))
答案 6 :(得分:4)
一般来说取决于
对于基于文件的东西,你几乎总是想尝试操作并处理失败而不是先检查。原因是文件系统是共享资源,并且您不能保证在file.exists返回true之后文件确实存在,因为某些其他进程可能同时删除了它。
答案 7 :(得分:4)
正如一些答案已经指出的那样,这取决于。
如果/ else用于流控制,那么可以使用添加的正例来捕获发生的错误。但是,正如Turowicz所指出的那样,对于很多人来说这被认为是不好的做法,使用try / catch超过你所需要的最低值。
您可以随时阅读Ned Batchelder中的这些文章(关于返回代码的说明,作为使用例外的替代方法)和Joel Spolsky(为什么他不喜欢使用例外编程)来了解还有别的想法,然后让自己的想法。
答案 8 :(得分:4)
只是一个想法......其中一个答案是你应该尝试一下,例如,如果你有零除可能性。我想知道为什么?你掌握在这里,你可以在分裂之前进行检查,并采取行动。如果它为零,你就不需要进行除法,而是执行另一个逻辑。
我只会在您无法控制或不能(或没有意义)事先检查事物(打开文件,......)的情况下使用try catch。
在你的情况下,我会使用File.Exists并尝试/ catch。 File.Exists作为业务检查(不需要在不存在时打开它),尝试/ catch来捕获打开文件时可能发生的任何异常。
答案 9 :(得分:2)
当文件不存在时,请先检查是否存在。但是当丢失的文件是一个异常状态时,你应该指出这个异常状态,但有异常。
所以基本的想法是: 尽量避免在可预期的情况下出现异常。
答案 10 :(得分:2)
一般来说,你应该同时做两件事。 try / catch以避免异常情况(文件突然从另一个线程中删除)。如果/ else处理非异常(检查文件是否存在)。 Try / catch比通常的if / else慢,所以不值得将它用于所有东西。
答案 11 :(得分:2)
在做出这些决定时,“异常应该例外”的格言很有用。主要是您应该使用标准程序流(即if语句)处理已知情况,以便异常代表意外情况(即错误)。
当然,就像任何规则一样,它会被打破。
另外,我不会太担心异常处理对性能的影响。在极端情况下,开销几乎可以忽略不计。
答案 12 :(得分:1)
当您已经可以在执行某个情况之前对其进行处理时,则应使用if-else。但是在某些情况下,除非您实际进行操作,否则不知道它是否会起作用,请使用try-catch。
情况1:有效使用Try-Catch
boolean isNumber(String input) {
try {
Integer.parseInt(input);
return true;
} catch (NumberFormatException) {
return false;
}
}
在实际“尝试”解析输入之前,您不知道输入是否为数字。因此,请使用try-catch。
情况2:有效使用if-else
boolean isNotNull(Object o) {
if (o != null) {
return true;
} else {
return false;
}
}
在对对象调用方法之前,我可以知道该对象为null。因此,请使用if-else。
情况3:如果if-else足够,则无效使用try-catch
boolean isNotNull(Object o) {
try {
// Some operation of object to know it's not null
o.hashCode();
return true;
} catch (NullPointerException e) {
return false;
}
}
提示:使用if-else作为应用程序的保护措施,例如检查空值,处理边缘情况等。要定义不同的应用程序流,请使用多态性以更好地进行状态管理。
答案 13 :(得分:0)
为此您知道文件退出问题。所以你更喜欢别的。
如果您不知道问题,最好使用try catch。
我建议两者,如下所示
try
{
if(File.Exists(path))
{
do work
}
else
{
messagebox.show("File Path Not Exit");
}
}
catch(Exception e)
{
messagebox.show(e);
}
它捕获了我们没有想到的所有错误。
答案 14 :(得分:0)
从所有答案中可以明显看出,没有标准/批准的方式来决定您是否使用其中一种。如果正确完成,两种方法都将有效。如果操作不正确,两种方法都会效率低下。
我更喜欢if / else语句,当它有意义时(即在我自己的函数中)和Try语句,当我调用函数时我无法控制。
在上面的示例中,如果您控制文件(意味着没有其他程序可能会操纵它),File.Exists()就足够了,但如果文件在检查和使用之间有可能消失则不够。
根据我的经验,在大多数情况下,文件操作通常可以更好地处理异常,因为在c#中这些非常大的文件操作会引发异常。它们不会返回可以使用if语句检查的错误代码。