【问题标题】:Why use specific exception catch blocks为什么使用特定的异常捕获块
【发布时间】:2018-05-12 10:45:52
【问题描述】:

在下面的代码中,我有一个 System.Data.Entity.Infrastructure.DbUpdateException 类异常的 catch 块。

我的问题是为什么我不能使用Exception 类来捕获我的代码中的每一个可能的异常并获取堆栈跟踪?

特定异常类型及其在多个 catch 块中的使用有何优势?

try
{
    AddAdminUserInput input1 = JsonConvert.DeserializeObject<AddAdminUserInput>(input);
    Foundation_Services_DL_DataEntities Db = DLMetadataContext.GetContext();
    UserAccount account = new UserAccount
    {
        emplid = input1.emplid,
        sso = input1.sso,
        deptid = input1.deptid,
        usertype = input1.usertype,
        status = input1.status,
        username = input1.username
    };

    Db.UserAccounts.Add(account);
    Db.SaveChanges();

    Dictionary<string, string> dict = new Dictionary<string, string>();
    dict.Add("status", "0");
    dict.Add("message", "User Addition Successful");

    Context.Response.Write(JsonConvert.SerializeObject(dict));
}
catch (System.Data.Entity.Infrastructure.DbUpdateException dbev)
{
    Dictionary<string, string> dict = new Dictionary<string, string>();
    dict.Add("status", "1");
    dict.Add("message", "User Addition Failed - User Already Exists");

    Context.Response.Write(JsonConvert.SerializeObject(dict));
}

【问题讨论】:

  • My question is that why i can't use Exception class to catch each and every possible exception in my code? 如果你这样做了,你会如何为不同的异常提供不同的status 代码?
  • 您的问题的答案是您可以使用Exception 来捕获所有问题。如果您不使用细节来缩小问题的位置,那么当您遇到问题时,您将头疼识别和解决问题。
  • 这是一个合法且可以回答的问题 - 我不理解近距离投票,除非它是一个骗子。

标签: c# asp.net exception-handling


【解决方案1】:

特定异常类型及其在多个 catch 块中的使用有何优势?

问同样问题的更好方法是“捕获不太具体的异常类型有什么缺点”。这个问题的答案非常简单:您可能会无意中捕获一个您不知道如何处理的异常。

通常,代码只有在知道如何处理异常时才应捕获异常,例如报告错误,使用计数器重试,请最终用户决定如何继续,等等。仅当您将捕获的异常限制为特定组时才有可能,例如DbUpdateException

捕获特定异常的一个不错的“奖励”是您可以访问仅在特定子类上定义的属性和方法。例如,DbUpdateException 通过Entries 属性告诉您哪些条目未能保存,这让您有机会尝试重试。

最后,某些异常只能在程序的顶层捕获。这些异常表示编程错误——例如,访问null 引用、访问末尾或负索引的数组、除以零等等。您的程序无法从这些错误中恢复,因为修复它们需要更改代码。因此,程序唯一能做的就是在退出或启动重新启动序列之前记录或以其他方式报告异常。

【讨论】:

  • +1 - 有时捕获任何异常并处理它们很有用,但尤其是在实用程序函数中,最好只捕获“预期”异常的子集。
【解决方案2】:

没有什么可以阻止您捕获异常,但不建议这样做,除非您只是想简单地记录异常并重新抛出它。

捕获特定异常允许您处理您知道如何修复的特定场景。

这里有一些关于异常、它们的行为方式以及如何最好地处理它们的非常好的信息https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/

【讨论】:

    【解决方案3】:

    您可以使用 catch all 异常,但如果您想要以不同方式处理特定异常,单独处理它们会很有用。在您的示例中,您将添加到字典中,然后可以提供一些有用的反馈而不是崩溃。对于 catch all 块,您将无法做到这一点。

    我使用过的一些代码的示例:

    catch (System.Runtime.InteropServices.COMException comException)
    {
        // Logout has already occurred
        this.VerboseLog($"Disconnect not required. ERROR LOGGED BUT WILL BE IGNORED; {comException}");
    }
    catch (Exception ex)
    {
       this.ErrorLog(ex);
       throw;
    }
    

    在这个第一次catch中,错误并不是真正的问题;它正在被记录,但它可以继续运行。在第二个捕获中,错误是一个问题,它被写入日志但不会进一步处理,因为我们不知道它是什么或如何处理它。

    【讨论】:

    • 这不是一个很好的答案——不是说它是错误的,而是它提供的东西不多。考虑添加示例和其他理由。查看其他一些答案,看看一个好的答案可能是什么样的。
    • 这很公平 - 我一直在寻找我的代码以找到一个示例,实际上并不是最容易搜索的东西
    • 你永远不应该这样做 throw ex; 其中ex 是一个捕获的异常。您丢失了堆栈跟踪。只需throw;
    • 现在看起来更好
    猜你喜欢
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 2021-05-13
    • 2010-09-07
    • 2012-11-11
    • 2012-08-27
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多