C#异常处理,哪个catch子句使用?

时间:2012-01-17 16:09:09

标签: c# exception-handling

  

可能重复:
  Catching specific vs. generic exceptions in c#

这是一个示例方法

private static void outputDictionaryContentsByDescending(Dictionary<string, int> list)
{
    try
    {
        //Outputs entire list in descending order
        foreach (KeyValuePair<string, int> pair in list.OrderByDescending(key => key.Value))
        {
            Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
        }
    }
    catch (Exception e)
    {
        MessageBox.Show(e.Message, "Error detected", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

我想知道除Exception之外使用什么异常子句以及使用更具体的catch子句是否有优势。

编辑:O.k感谢所有人

10 个答案:

答案 0 :(得分:7)

在语句中捕获各种类型的异常将允许您以不同的方式处理每种异常。

Exception的一揽子规则可能对记录和重新抛出异常非常有用,但对于实际处理您可以从中恢复的异常不是最好的。

try
{
    // open a file specified by the user
}
catch(FileNotFoundException ex)
{
    // notify user and re-prompt for file
}
catch(UnauthorizedAccessException ex)
{
    // inform user they don't have access, either re-prompt or close dialog
}
catch(Exception ex)
{
    Logger.LogException(ex);
    throw;
}

答案 1 :(得分:4)

您应该只捕获您期望代码可能抛出的异常。这样,如果它抛出你没想到的东西,它可能是一些关键的东西; 应该冒泡调用堆栈并可能导致应用程序崩溃的东西;或者你没想过的东西。

例如,您可能希望处理由I / O代码引发的IOException,以便您可以将问题转发回用户。但是,相同的操作可能会引发更为重要的操作,例如AccessViolationException。在这种情况下,您可能希望程序终止,或以不同的方式处理问题。

通用异常处理应该只在真正用于您不关心发生了什么错误的情况,并且随后不希望它影响您的其余进程。

答案 2 :(得分:2)

我在示例中看到的唯一可能的异常原因是list为空。 OrderByDescending()应返回空IEnumerable<>而不是空引用。

如果我读得正确,抓住NullReferenceException可能更有意义:

try
{
...
} catch (NullReferenceException exception)
{
  MessageBox.Show(...);
}

但是,这实际上取决于您的应用程序的需求。如果您的目的只是提醒用户或记录所有异常,那么捕获Exception类就可以了。如果您需要针对不同类型的异常进行特殊处理 - 例如发送电子邮件警报而不是仅记录消息 - 那么使用特定的异常类型是有意义的:

try
{
} 
catch(NullReferenceException e)
{
//...
} 
catch(StackOverflowException e)
{
//...
}
catch(Exception e)
{
/// generic exception handler
}

答案 3 :(得分:2)

使用哪个例外实际上取决于try块中的代码。一般而言,您希望捕获可以执行某些操作的异常,并让您没有权限的异常移动到您的代码的高级别,您可以执行某些操作。我看到人们犯的最常见错误之一是试图捕捉他们无法处理的错误。

例如

Void ChoseFile()
{
     try
     { 
         string FileName = GetInputFile()
     }    
     catch( InvalidFileSelectedException ex)
     { 
         //In this case we have some application specific exception 
         //There may be a business logic failure we have some ability 
         //to infomr the user or do an action that makes sense  
     }
     catch(FileNotFoundException exfilenot found)
     { 
         //In this case we can do somthing different the the above 
     }
     catch(Exception ) 
     { 
         //Normal I would not use this case we have an error we don't know what to do 
         //with. We may not have a usefull action.  At best we can log this exception                               
         // and rethrow it to a higher level of the application that can inform the user
         // fail the attempted action.  Catching here would only suppress the failure.
      }

} 

答案 4 :(得分:1)

由于您正在处理字典..那么您想要查看这两个例外

  • keyValuePair的键是一个空引用(在Visual Basic中为Nothing)。

  • ArgumentException字典中已存在具有相同键的元素(TKey,TValue)。

    KekValuePair Exception 这取自MSDN网站

答案 5 :(得分:1)

您应该始终使用特定类来捕获异常。

如果您知道如果文件被锁定该怎么办,但您认为所有其他错误都是意外且无法处理的,那么您应该抓住System.IO.IOException并处理错误。您应该只抓住Exception(或只是catch {)才能正常退出。

答案 6 :(得分:0)

使用您可能期望但仍然无法阻止的异常类型,并且您可以充分处理。让任何其他东西冒泡到某个可能期望它或可以处理它的地方。

在这种情况下,如果字典为空,我可能会遇到NullReferenceException但是我不会抓住它。这是我可以反而验证的东西

if (dictionary != null) 

所以没有理由允许甚至发生异常。切勿使用控制流的异常,并根据已知原因进行验证。

答案 7 :(得分:0)

某些类/方法会抛出不同的异常,具体取决于错误。例如,您可能正在使用File类将数据写入文件。您可以为可以从中恢复的异常类型编写多个Catch语句,并使用一般的异常捕获来记录和冒泡任何无法从中恢复的内容。

答案 8 :(得分:0)

通过使用Exception,您可以捕获所有异常。在使用IOException或StackOverflowException时,您只会捕获该类型的错误。

由异常捕获的StackOverflowException仍然保持相同的消息,堆栈跟踪等。

答案 9 :(得分:0)

异常处理理念 我相信你可以找到许多其他的哲学

防守代码。捕获异常比首先防止错误更加昂贵。

不要抓住异常并通过不处理来掩埋它。您可能需要花费很多时间来查找已被抑制的错误。

记录您捕获的错误。 这有助于分析问题。您可以检查是否有多个用户遇到同样的问题 我更喜欢用于记录的数据库,但是平面文件或事件日志也是合适的。 数据库解决方案最容易分析,但可能会引入其他错误。

如果错误是由用户输入的错误数据引起的,请告知用户问题并允许他们重试。 如果他们无法解决问题,请始终允许逃生路线。

尽可能靠近源捕获错误 这可以是数据库过程,数据访问层(DAL)中的方法或其他位置。

处理异常与捕获异常不同。您可能需要重新抛出异常,以便可以在堆栈或UI中更高的位置处理它。

至少可以通过两种方式重新处理异常。     throw本身并不会改变堆栈。     throw ex确实会改变或添加到堆栈中而没有任何好处。

有时最好不要捕捉异常,而是让它冒出来。

如果您正在编写没有用户界面(UI)的服务(Web或Windows),则应始终记录错误。 同样,这是因为有人可以分析日志或数据库文件以确定发生了什么。

您总是希望有人知道发生了错误。

对try块有很多catch语句可能会使代码更难维护,尤其是当catch块中的逻辑很复杂时。 相反,代码是防御性的。

请记住,您可以在catch块中尝试catch块。

另外,不要忘记在适当的地方使用finally块。 例如,关闭数据库连接或文件句柄等

HTH HARV