C# 在异常处理方面,哪种做法更好?

C# 在异常处理方面,哪种做法更好?,c#,exception-handling,C#,Exception Handling,如果我有一个特殊的例外情况,我预计它将发生; 例如,为了处理它,我选择在它发生时显示一条错误消息,这样做更好,为什么 解释代码: try { string result = dictionary[key]; } catch (KeyNotFoundException e) { //display error } 或: 第二种方法更好。异常抛出可能非常昂贵。通常,异常用于指示异常情况—通常不会发生,但您的程序仍需要优雅地处理(例如文件无法访问或只读,网络连接中断)。正常的控制

如果我有一个特殊的例外情况,我预计它将发生; 例如,为了处理它,我选择在它发生时显示一条错误消息,这样做更好,为什么

解释代码:

try
{
    string result = dictionary[key];
}
catch (KeyNotFoundException e) 
{ 
    //display error
}
或:


第二种方法更好。异常抛出可能非常昂贵。

通常,异常用于指示异常情况—通常不会发生,但您的程序仍需要优雅地处理(例如文件无法访问或只读,网络连接中断)。正常的控制流,如检查字典中的值,如果有一个等效函数在不使用异常的情况下具有相同的效果,则不应使用异常

在代码中使用额外的try/catch语句也会降低代码的可读性,并且在代码块周围使用异常处理程序会对CLR造成某些限制,从而导致性能下降

在您的示例中,如果预期字典将具有某个键值,我将执行以下操作

string result;
if (!dictionary.TryGetValue(key, out result)
{
    // display error
    return;   // or throw a specific exception if it really is a fatal error
}

// continue normal processing

这比在元素访问中使用异常处理程序要清楚得多第二种方法更好,至少有三个原因:

1) 更清楚。作为代码的读者,我希望出现一个异常,表明出现了错误,即使它已被处理

2) 在使用VisualStudio进行调试时,经常会中断所有异常,这使得处理总是抛出异常的代码有点烦人


3) 第二个版本更快,但效果非常小,除非您在一段时间关键的代码中每秒抛出许多异常。

第二种方法更好,因为抛出和hanlding异常会影响性能。超过每秒100次的投掷速度可能会显著影响性能-
大多数应用程序的性能。考虑.Ex/P>< P>异常处理是最有用的,当你需要提供一种简单的方法来摆脱困难的情况时,它可以大大简化代码并减少角形错误的潜在可能性。
在这种非常简单的情况下,它没有什么优势,而且由于它的性能损失,在这种情况下不应该使用。

这完全取决于应用程序正在做什么以及特定代码正在做什么

正如该公司所说,例外情况应用于例外情况。以写入文件为例。如果检查文件是否存在会使应用程序速度减慢和/或文件缺失是一个严重问题,则允许出现异常并捕获该异常。如果不是很关键,或者重新创建文件不是问题,那么首先执行文件存在性检查

我看到有人认为所有的错误处理都应该通过异常来完成(最近一次是在年),但我不同意

第二种选择比第一种好。由于您希望这种情况正常发生,因此最好避免异常。异常最好只用于异常情况,即您无法轻松预测和测试的情况

但是,最好的选择是TryGetValue方法,因为它同时执行检查和获取:

if (dictionary.TryGetValue(key, out result)) {
   // use the result
} else {
   // display error
}

只是提醒一下。这也不例外。 一个例外是听起来像“我的UNIX机器上没有/etc”。 若你们理解错误,你们会写出错误的代码,如上图所示


这在很大程度上取决于词典的作用。如果由于程序设计的原因很有可能找不到密钥,则应执行trygetvalue。但是,如果程序的设计使得找不到键是一个异常事件,那么应该使用异常处理程序方法

第二种方法可能更好。请记住,例外情况用于特殊情况。使用此原则指导您的决策:

  • 如果您要求密钥作为应用程序不变量存在于字典中,那么假设它存在,如果不存在则处理异常
  • 如果应用程序代码不要求该条目存在于字典中,则首先调用
    ContainsKey()
我的猜测是,后者可能是正确的行动方针

免责声明:我通常不认为性能应该是这里的首要考虑因素。只有当您证明自己存在瓶颈时,才能让性能影响您的决策!在此之前的任何操作都会导致应用程序代码不必要的复杂化


你的例子让我有点不舒服,因为它似乎自由地混合了“逻辑材料”和“显示材料”。例如,如果有人想在命令行应用程序中重用您的业务逻辑,该怎么办?通常,更好的方法是让逻辑函数累积错误并将其返回给调用方,调用方可以决定如何处理这些错误。rossfabricant,您应该看到我使用的代码。业务逻辑和业务规则被认为是相同的,因此所有业务逻辑要么在显示层,要么在数据访问层。当我问到如何将业务逻辑提取到它自己的逻辑层时,我被告知不需要另一个级别的间接寻址。我不同意,但也许穆斯塔法的情况也是如此+1最佳实践。你能为你的上一次陈述提供来源(或证据)吗?我没有意识到这一点。我的理解是,从性能角度来看,try/catch块基本上是免费的,只要您不抛出异常。我从一本书中记得这一点,我需要在周一检查。首先,CLR没有内联包含异常处理程序的方法-@Steve:是的,如果你没有抛出异常,那么进入/退出try块的性能影响可以忽略不计。问题是,如果预期的情况是密钥可能不存在,那么应该有更好/更简单的机制
if (dictionary.TryGetValue(key, out result)) {
   // use the result
} else {
   // display error
}