如何在使用if/else和try/catch之间做出决定
本文关键字:catch try 之间 决定 else if | 更新日期: 2023-09-27 17:58:07
在编写代码时,如何在使用if
/else
还是try
/catch
之间做出决定?例如,在检查文件时,是否应该基于以下方法:
if (File.Exists("file.txt"))
{
//do stuff
}
还是try
/catch
块?
另一个例子:对文件的写入可以通过if
/else
块来处理,以创建一个文件,然后对其进行写入,或者在假设文件存在的情况下通过try
/catch
来处理。选择时有哪些考虑因素?
您永远不应该使用try/catch进行流控制。
生成异常是一项极其昂贵的操作。如果/else更快更干净。
在处理文件时,您应该始终使用try/catch,因为文件的状态可能会在程序之外更改。
考虑以下代码位:
if(File.Exists("file.txt"))
File.Delete("file.txt")
该文件可能已在if语句之后、Delete()
调用之前被另一个进程删除。当您尝试删除它时,会引发一个异常。
在处理文件时,还有很多事情需要考虑,你可能无法用if捕捉到,例如,文件在网络连接上不可用,访问权限更改,硬盘故障等。
这些事情超出了程序的控制范围,因此应该设置异常处理程序。
如果您认为操作通常应该成功,那么try/catch
可能更容易读取。特别是,如果存在许多失败原因(多个catch
块)。
否则,如果它有时成功,有时失败——而且是由于特定的原因,请使用if/else
(这被称为结构化异常处理)。
有些人指出,使用try/catch
进行异常处理可能非常耗时。我倾向于按照以下几行来阅读这样的建议:如果您的分析表明存在性能问题,请不要在紧密的内部循环中这样做。在编写初稿时,根本不用考虑在这个级别进行优化!
只是为了让这个话题停下来(是的,这个问题是8个月前提出的,但互联网总是知道的!),我决定进行一个小测试,测试哪个更有效如果你很确定你不会有例外——例如,"其他"部分只会发生0.001%的时间。事实证明,如果你从不必须捕获/其他任何东西,那么尝试捕获的速度大约快4%(无论如何,在我的机器上)。以下是代码和附带的结果:
情况1:如果其他情况:
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、75314.308、7323.4188。
平均=7446.82592毫秒
情况2:尝试捕获:
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毫秒
结论(基于这个相当简单的例子;实际里程可能会有所不同,等等):
就纯粹的数字而言,如果你非常确定不会发生异常/else情况,那么try-catch比每次执行"if"子句快大约4%。
只是一个想法。。。其中一个答案是,例如,如果你的可能性为零,你应该尝试接球。我想知道为什么?你在这里掌控一切,你可以在分开之前进行检查,并采取行动。如果它为零,您就不需要进行除法运算,而是执行另一个逻辑。
我只会在你无法控制或无法(或没有意义)事先检查(打开文件,…)的情况下使用try-catch
在你的情况下,我会使用File.Exists和try/catch。文件。作为业务检查存在(不存在时无需打开它),尝试/catch捕获打开文件时可能发生的任何异常。
通常取决于
对于基于文件的东西,你几乎总是想尝试操作并处理失败,而不是先检查。原因是文件系统是一个共享资源,您不能保证在file.exists返回true后,文件确实存在,因为其他进程可能同时删除了它。
当可能发生意外(异常)并且您想对此做一些特别的事情时,您可以使用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块,因为在对文件进行任何操作之前都可以检查文件的存在与否。
只有在特殊情况下才能执行或使用异常处理。
在一个取决于文件是否存在的场景中,当你可以简单地进行时,使用try-catch块是没有意义的
if(File.Exists(path))
{
}
else
{
}
异常处理会对性能造成很大影响,因此请尝试通过在代码中应用更多检查来最大限度地减少异常情况,如File.Exists(path))
正如一些答案已经指出的那样,这取决于情况。
If/else用于流控制,但添加了捕获发生的错误的Exceptions也可以。但正如Turowicz所指出的,对很多人来说,使用尝试/捕捉超过所需的最小值是一种糟糕的做法
你可以阅读Ned Batchelder(谈论返回代码,作为使用异常的替代方案)和Joel Spolsky(为什么他不喜欢使用异常编程)的这些文章,了解其他人对异常的看法,然后自己下定决心。
当文件不存在时,首先检查是否存在。但是,当丢失的文件是一种异常状态时,您应该用异常来指示这种异常状态。
因此,基本思想是:尽量避免在可预期的情况下出现例外。
通常您应该同时执行这两项操作。尝试/catch以避免出现异常情况(文件突然从另一个线程中删除)。和if/else来处理非异常(检查文件是否存在)。Try/catch比通常的if/else相对较慢,因此不值得在所有情况下都使用它。
格言"异常应该是异常的"在做出此类决策时很有用。主要是,您应该使用标准程序流(即if语句)处理已知情况,以便异常表示意外情况(即错误)。
当然,就像任何规则一样,它是要被打破的。
此外,我不会太担心异常处理对性能的影响。除了极端情况外,其他情况下的开销几乎可以忽略不计。
当您在执行之前已经可以处理一种情况时,您应该使用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:如果其他方法可以满足,则尝试捕获的使用无效
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作为应用程序的保护,如检查null值、处理边缘情况等。对于定义不同的应用程序流,使用多态性可以更好地进行状态管理。
从所有答案中可以明显看出,没有标准/批准的方法来决定是否应该使用其中一种。如果做得正确,这两种方法都会有效。如果操作不正确,这两种方法都将效率低下。
当if/else语句有意义时(即在我自己的函数中),我更喜欢它;当我调用我无法控制的函数时,我喜欢Try块。
在上面的示例中,文件。如果您控制该文件(意味着没有其他程序可能操作它),Exists()就足够了,但如果该文件有可能在检查和使用之间切换,就不够了。
根据我的经验,通常情况下,文件操作在大多数情况下都能更好地处理异常,因为这些文件操作在c#中会引发异常。它们不返回可以使用if语句检查的错误代码。
为此,您知道文件退出问题。所以你更喜欢其他。
如果你不知道这个问题,最好用try-catch。
我建议两者都选,就像下面的
try
{
if(File.Exists(path))
{
do work
}
else
{
messagebox.show("File Path Not Exit");
}
}
catch(Exception e)
{
messagebox.show(e);
}
它抓住了所有的错误,而我们没有想到。