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

时间:2011-05-31 10:41:25

标签: c#

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

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

由于

15 个答案:

答案 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语句检查的错误代码。