1

我听说 try/catch 被认为对性能不利,但是如果您很少期望抛出异常,那么它们被认为是返回失败信息的更好方法,而不是使用具有布尔值的方法/函数。

以这种方式使用 try/catch 对性能是好还是坏?它当然使编码更容易。

例子:

void DoSomething(){
  try{
    DoSomethingIffy();
  } catch {
    // Yikes! Do failure stuff
  }
}

void DoSomethingIffy(){
  if (rareCondition) {
    throw new Exception("oops");
  }
}

对比

void DoSomething(){
  if (!DoSomethingIffy()) {
    // Yikes! Do failure stuff
  }
}

bool DoSomethingIffy(){
  if (rareCondition) {
    return false;
  }
  else {
    return true;
  }
}
4

2 回答 2

1

如果您看到或期望看到每秒超过 100 次的投掷率,那么它可能会对性能产生影响。(请参阅 .NET Framework 设计指南:异常抛出)在这种情况下,使用避免在代码的“热”部分中抛出异常的设计将是有益的。

考虑一下,如果这是代码的性能关键部分,您可能每秒输入 1,000,000 次,并且 1,000 分之一的抛出概率可能是“罕见的”,但它可能会导致性能下降到无法接受的程度。

您确实必须针对真实的用户场景测量这些东西并收集数据,以从性能角度了解一种或另一种设计是否会变得更好(或值得实施更复杂的设计)。

在数据方面,.NET 提供了专门与异常相关的性能计数器,这在遇到性能问题时可以提供有用的诊断。

于 2013-09-06T02:59:34.087 回答
1

这真的取决于情况。Try/Catch 通常比 if/else 对性能的影响更大(同样,这真的取决于情况),但 try/catch 块也是良好错误处理的一部分。作为最佳实践(为了更好的性能和代码可维护性),最好通过将它们置于更高级别来限制 try/catch 块的数量。例如,如果您有一个名为“Car”的类具有“Drive”方法,并且该方法调用 Car.StartEngine() 和 Person.FastenSeatBelt()(并假设两种方法都可能出现异常),那么不要尝试/catch 在 StartEngine 方法中和另一个在 FastenSeatBelt 方法中,

在决定是使用 if/else 还是 try/catch 时,还有一些需要考虑的因素。假设您有一个方法 ConvertToCamelCase(string)。如果为字符串参数传递了 null,您想做什么?就个人而言,我更愿意让这个方法抛出 ArgumentNullException。然后,如果我需要记录或处理异常,我会在调用方法中使用 try/catch 块。但是,如果您决定无论参数是否为空都返回真/假,我建议将此方法重命名为 TryConvertToCamelCase(string)。这个命名约定向调用者建议他们不需要担心从这个方法中抛出异常,因为如果它因任何原因失败,它会尝试返回 false。

要考虑的另一件事是您是否可以优雅地处理“异常”并从您当前所在的代码部分继续。例如,假设我有一个 Windows 窗体,它只是打开用户在单击“打开”后在文本框中指定的文件。如果我在按钮单击的事件处理程序中进行文件处理,我会将处理打开文件的代码放在 if 语句中,条件是 File.Exists。如果文件不存在,它将转到 else 块,并弹出一个消息框,让用户知道该文件不存在。但是,如果事件处理程序改为使用我创建的帮助程序类,让我们称之为“FileHelper”,那么 FileHelper 的“ReadFile”方法甚至不会费心检查文件是否存在,它只会尝试打开它,如果它不能打开,则会抛出 FileNotFoundException。然后我的按钮单击事件处理程序将捕获异常并提醒用户。原因是“FileHelper”类不知道表单或任何用户交互。如果“ReadFile”方法无法打开文件,则无法继续,所以是个例外。

我要提到的最后一件事是确保当您处理错误时,这是​​您所期望的错误。通常,我看到开发人员执行“catch (Exception ex)”,然后通过提示用户来处理错误。但是,使用前面的 ReadFile 方法,假设您将其作为 32 位应用程序运行,并且它已经消耗了 2GB 限制中的 1.9999 GB,也许不是“ex”是 FileNotFoundException,而是真的是 OutOfMemoryException。通过说“嘿,伙计,该文件不存在”来提示用户,当它确实增加了负面的用户体验时(不是说你会这样做,只是我经常看到的事情)。相反,您可以使用“catch (FileNotFoundException ex) {...}”或“catch (Exception ex) { if (ex is FileNotFoundException) {...

总结:当您需要记录或处理异常时,不要害怕使用 try/catch,但也不要对 try/catch 块发疯。

于 2013-09-06T03:49:06.707 回答