为什么要使用特定的异常捕获块
Why use specific exception catch blocks
在下面的代码中,我有一个用于 System.Data.Entity.Infrastructure.DbUpdateException
class 异常的 catch 块。
我的问题是,为什么我不能使用 Exception
class 来捕获代码中的每一个可能的异常并获取堆栈跟踪?
特定异常类型的优点是什么以及它们在多个 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));
}
您可以使用捕获所有异常,但如果您希望以不同方式处理特定异常,则单独处理它们可能会很有用。在您的示例中,您要添加到字典中,然后字典可以提供一些有用的反馈而不是崩溃。您将无法对所有块执行此操作。
我使用过的一些代码中的示例:
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错误并不是真正的问题;它正在被记录,但它可以继续 运行。在第二个捕获中,错误是一个正在写入日志的问题,但不会进一步处理,因为我们不知道它是什么或如何处理它。
What is the advantage of specific Exception types and their use in multiple catch blocks?
问同一个问题的更好方法是 "what is a disadvantage of catching less specific Exception types." 这个问题的答案非常简单:您可能会无意中捕捉到您不知道如何处理的异常。
通常,代码只有在知道如何处理异常时才应该捕获异常,例如报告错误,使用计数器重试,要求最终用户决定如何继续,等等。仅当您将捕获的异常限制为特定组时才有可能,例如 DbUpdateException
.
捕获特定异常的一个很好的 "bonus" 是您可以访问仅在特定子类上定义的属性和方法。例如,DbUpdateException
告诉您哪些条目未能通过 Entries
属性 保存,这让您有机会尝试重试。
最后,某些异常只能在程序的顶层捕获。这些异常表示编程错误 - 例如,访问 null
引用、访问数组末尾或负索引处的数组、除以零等。您的程序无法从这些错误中恢复,因为修复它们需要更改代码。因此,程序唯一可以做的就是在退出或启动重启序列之前记录或报告异常。
没有什么可以阻止您捕获异常,但不建议您这样做,除非您只想简单地记录异常并重新抛出它。
捕捉特定的异常可以让您处理您知道如何修复的特定场景。
这里有一些关于异常、它们的行为方式以及如何最好地处理它们的非常好的信息 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/
在下面的代码中,我有一个用于 System.Data.Entity.Infrastructure.DbUpdateException
class 异常的 catch 块。
我的问题是,为什么我不能使用 Exception
class 来捕获代码中的每一个可能的异常并获取堆栈跟踪?
特定异常类型的优点是什么以及它们在多个 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));
}
您可以使用捕获所有异常,但如果您希望以不同方式处理特定异常,则单独处理它们可能会很有用。在您的示例中,您要添加到字典中,然后字典可以提供一些有用的反馈而不是崩溃。您将无法对所有块执行此操作。
我使用过的一些代码中的示例:
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错误并不是真正的问题;它正在被记录,但它可以继续 运行。在第二个捕获中,错误是一个正在写入日志的问题,但不会进一步处理,因为我们不知道它是什么或如何处理它。
What is the advantage of specific Exception types and their use in multiple catch blocks?
问同一个问题的更好方法是 "what is a disadvantage of catching less specific Exception types." 这个问题的答案非常简单:您可能会无意中捕捉到您不知道如何处理的异常。
通常,代码只有在知道如何处理异常时才应该捕获异常,例如报告错误,使用计数器重试,要求最终用户决定如何继续,等等。仅当您将捕获的异常限制为特定组时才有可能,例如 DbUpdateException
.
捕获特定异常的一个很好的 "bonus" 是您可以访问仅在特定子类上定义的属性和方法。例如,DbUpdateException
告诉您哪些条目未能通过 Entries
属性 保存,这让您有机会尝试重试。
最后,某些异常只能在程序的顶层捕获。这些异常表示编程错误 - 例如,访问 null
引用、访问数组末尾或负索引处的数组、除以零等。您的程序无法从这些错误中恢复,因为修复它们需要更改代码。因此,程序唯一可以做的就是在退出或启动重启序列之前记录或报告异常。
没有什么可以阻止您捕获异常,但不建议您这样做,除非您只想简单地记录异常并重新抛出它。
捕捉特定的异常可以让您处理您知道如何修复的特定场景。
这里有一些关于异常、它们的行为方式以及如何最好地处理它们的非常好的信息 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/