为什么大多数时候建议我们不应该捕获“异常”之类的错误,而是捕获我们作为开发人员所期望的错误。捕获通用错误是否会影响性能,还是从最佳实践的角度推荐?
try
{
// Do something
}
catch(Exception e)
{
//Log error
}
为什么大多数时候建议我们不应该捕获“异常”之类的错误,而是捕获我们作为开发人员所期望的错误。捕获通用错误是否会影响性能,还是从最佳实践的角度推荐?
try
{
// Do something
}
catch(Exception e)
{
//Log error
}
最佳实践是先捕获特定异常,然后再处理更通用的异常。
可以将具有不同异常过滤器的多个 catch 块链接在一起。catch 块在您的代码中从上到下进行评估,但对于每个抛出的异常只执行一个 catch 块。执行指定所引发异常的确切类型或基类的第一个 catch 块。如果没有 catch 块指定匹配的异常过滤器,则选择没有过滤器的 catch 块(如果语句中存在一个过滤器)。首先定位具有最具体(即最衍生的)异常类型的 catch 块很重要。
对于您的问题:
为什么大多数时候建议我们不应该捕获“异常”之类的错误,而是捕获我们作为开发人员所期望的错误。
一个例子是捕捉NullReferenceException。捕获 NullReferenceException 从来都不是一种更好的做法,相反,在使用其实例成员之前,应该始终检查对象是否为空。例如在字符串的情况下。
string str = null;
try
{
Console.WriteLine(str.Length)
}
catch(NullReferenceException ne)
{
//exception handling.
}
相反,应该进行检查以检查空值。
if(str != null)
Console.WriteLine(str.Length);
编辑:
我想我的问题是错误的,如果你问的是哪个异常应该被捕获,哪些不应该那么 IMO,那些可以处理的异常应该被捕获并且休息应该留在图书馆,这样它们就可以冒泡到上层进行适当处理的层。一个例子是违反主键约束。如果应用程序正在从用户那里获取输入(包括主键)并且该日期被插入到数据库中,则可以捕获该异常并向用户显示一条消息“记录已存在”,然后让用户输入一些不同的价值。
但是,如果异常与外键约束相关(例如,下拉列表中的某些值被认为是无效的外键),那么该异常应该冒泡并且通用异常处理程序应该将其记录在适当的位置。
例如,在 ASP.Net 应用程序中,这些异常可以记录在 Application_Error 事件中,并且可以向用户显示一般错误页面。
编辑2: 对于OP的评论:
如果在低级别,尽管知道错误是否为 sqlexception,但在捕获一般错误时是否会出现性能下降
即使会有任何性能差异,它也应该可以忽略不计。但是捕获特定的异常,如果您知道异常将要发生,SqlException
那么就捕获它。
您应该只捕获您可以处理的异常。Exception
太通用了,所以大多数时候你不能说你可以处理。这有点好笑,但您应该只捕获除您之外的异常:)
有些情况你需要捕捉Exception
但很少见,你应该在大多数情况下避免它。通常它表示一些设计问题。
查看Eric Lippert 的博客(Vexing exceptions)了解处理异常的最佳方式。
• 不要捕获致命异常;无论如何,您对它们无能为力,并且试图通常会使情况变得更糟。
• 修复您的代码,使其永远不会触发愚蠢的异常——“索引超出范围”异常不应该在生产代码中发生。
• 通过调用那些在非异常情况下抛出的令人烦恼的方法的“Try”版本,尽可能避免令人烦恼的异常。如果你无法避免调用一个令人头疼的方法,请捕捉它令人头疼的异常。
• 始终处理表示意外外部条件的异常;一般来说,预测每一个可能的失败是不值得或不切实际的。只需尝试操作并准备处理异常。
捕获您打算处理的那些异常。您通常希望在这样的上下文(方法)中处理特定的异常,在这种情况下,您有足够的信息来处理报告的错误(例如,访问用于清理的对象)。
如果try
块内的代码抛出不同类型的异常,您可能希望在同一方法中处理一些异常并重新抛出其他异常,以便在调用方方法中处理它们(因为在该上下文中,您有处理这些异常的资源)。
比要求更频繁地使用异常处理实际上是一种懒惰的编程方式。假设你有一个DataTable
并且你想访问第一行。
public DataRow AccessFirstRow(DataTable dt)
{
try
{
return dt.Rows[0];
}
catch (Exception e)
{
//There isn't a first row or dt is null
}
}
代替
public DataRow AccessFirstRow(DataTable dt)
{
if(dt != null)
if(dt.Rows.Count > 0)
return dt.Rows[0];
//If we can't access dt, then don't
return null;
}
我的经验法则是:
例外只应在例外情况下使用。
但是,如果您确实决定处理它们,则如上所述处理您知道可能会遇到的特定异常,而不是通用异常。
这是一个最佳实践。这个想法是,您应该快速明确地处理已知异常,同时在程序中拥有更普遍的异常,因为意外异常可能是由一些更主要/基本错误引起的。