如何在使用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来处理。选择时有哪些考虑因素?

如何在使用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); 
}

它抓住了所有的错误,而我们没有想到。