我已经习惯了在每一个方法有try / catch块。 这样做的原因是为了让我能赶上在违规的每一个点异常并记录它。 我明白了,从我的阅读和与他人的对话,这是不是一个流行的观点。 每个人都应该只赶上一个什么准备处理。 但是,如果我没有在违规的点赶上的话,那就有可能永远日志违规和了解它。 注意:当我赶不处理,我还是扔。 这让我让异常传播的东西,将处理它,但还是让我在违规的点记录它。
所以...怎样才能避免try / catch语句中的每一个方法,但仍然记录错误处所发生的呢?
我已经习惯了在每一个方法有try / catch块。 这样做的原因是为了让我能赶上在违规的每一个点异常并记录它。 我明白了,从我的阅读和与他人的对话,这是不是一个流行的观点。 每个人都应该只赶上一个什么准备处理。 但是,如果我没有在违规的点赶上的话,那就有可能永远日志违规和了解它。 注意:当我赶不处理,我还是扔。 这让我让异常传播的东西,将处理它,但还是让我在违规的点记录它。
所以...怎样才能避免try / catch语句中的每一个方法,但仍然记录错误处所发生的呢?
不,不抓的一切。 例外传播到堆栈上高。 所有你需要做的是确保它得到堆栈的顶部之前的异常被捕获。
这意味着,例如,你应该围绕一个事件处理程序的代码用try / catch块。 事件处理程序可能是“栈顶”。 同为一个ThreadStart处理程序或从异步方法的回调。
你也想赶上层边界例外,但在这种情况下,你可能只是想换行例外层特定的例外。
在ASP.NET的情况下,你可能会决定允许ASP.NET运行状况监视登录异常为您服务。
但你肯定不会在任何时候需要抓住每方法例外。 这是一个重大的反模式。 我会大声反对你的代码之类的异常处理检查。
你可以看到一切在堆栈跟踪 - 没有必要的try / catch每个方法。
坚持几个原则:
OK,看了所有的答案说你应该在顶层一个try / catch语句,我会用另一种观点来衡量英寸
我不会把一个try / catch在每一个方法,远非如此。 但我会用身边,我预计将失败的代码段一个try / catch(如打开文件),并在那里我想更多的信息添加到异常(要记录越往上链)。
堆栈跟踪说法和消息说“权限被拒绝”可能足以让你作为一个程序员找出什么地方错了,但我的目标是为用户提供有意义的信息的用户 ,如“无法打开文件“C: \ lockedfile.txt”权限被拒绝。“
如:
private void DoSomethingWithFile(string filename)
{
// Note: try/catch doesn't need to surround the whole method...
if (File.Exists(filename))
{
try
{
// do something involving the file
}
catch (Exception ex)
{
throw new ApplicationException(string.Format("Cannot do something with file '{0}'.", filename), ex);
}
}
}
我也想提一提,即使是人说:“只有一个的try / catch”大概还是使用try /终于在他们的代码,因为这是为保证适当的清理等的唯一途径
为了在发生点做到这一点,你仍然需要一个try / catch。 但你并不一定需要到处捕捉到的异常。 他们沿着调用堆栈,以及他们被发现的时候,你会得到一个堆栈跟踪。 所以,如果有问题出现时,您可以根据需要随时添加更多的尝试/捕获。
考虑检查出可用的许多日志框架之一。
我不认为你需要要抓违规点应有尽有。 你可以泡你的例外,然后使用堆栈跟踪来找出违规的点实际出现。
另外,如果你需要有一个try catch块,我听到的最好的办法是将它隔离的方法,以不扰乱巨大的try catch块的代码。 此外,还要在try语句尽可能少的语句越好。
当然,只是重申一下,你的异常冒泡到顶部和记录堆栈跟踪比嵌套的try-catch-LOG-扔块都在你的代码的更好方法。
我会考虑使用ELMAH进行异常处理,这是相当多的概念“让例外发生。” ELMAH将记录他们的照顾,你甚至可以将其设置为向您发送电子邮件时,一定项目例外达到或超过规定的阈值。 在我的部门,我们留下尽可能远离try / catch块地。 如果事情是错误的应用程序,我们想马上知道这个问题,所以我们可以解决它,而不是抑制异常,并在代码中处理它的东西。
如果有异常情况发生,这意味着的东西是不正确的。 这样做是为了让您的应用程序只做自己应该做的。 如果它做一些不同的尝试导致异常的,你的反应应该是解决它的发生原因,不会让它发生在代码处理。 这仅仅是我的/我们的理念,它并不适合所有人。 但是,我们都被应用“吃”出于某种原因或其他异常燃烧的方式太多次,没有人知道什么是错的。
和永远,永远,永远赶上一般例外。 永远,永远,永远抓住最具体的异常,因此如果有异常抛出,但它不是你期待的类型,再一次,你就会知道,因为该应用程序会崩溃。 如果你正好赶上(例外五),那么无论是抛出异常的类型,你的catch块现在将负责应对每一个类型的异常可能可能被抛出。 如果没有,那么你碰上了整个“吃”有例外,事情错了,但你永远不知道,直到它可能为时已晚。
如何在每一个方法避免try / catch语句,但仍然记录错误处所发生的呢?
这取决于托管ENV。 Asp.Net,的WinForms和WPF都捕捉未处理的异常的不同方式。 但是,一旦全球处理器是通过一个例外情况下,你可以决定从异常抛出点,为每个异常包括堆栈跟踪。
我绝对不使用尝试捕捉包装周围的每一个方法(奇怪的是,我没有当我第一次开始,但是那是以前我学到更好的方法)。
1)为了防止崩溃程序和用户失去他们的信息,我这样做
runProgram:
try
{
container.ShowDialog();
}
catch (Exception ex)
{
ExceptionManager.Publish(ex);
if (MessageBox.Show("A fatal error has occurred. Please save work and restart program. Would you like to try to continue?", "Fatal Error", MessageBoxButtons.YesNo) == DialogResult.Yes)
goto runProgram;
container.Close();
}
容器是我的应用程序开始的地方所以这基本上使包装在我的整个应用程序,所以,没有什么会导致无法恢复的崩溃。 这是少有的情况下,我不介意使用goto语句之一(这是一个很小的代码量,并仍然相当可读)
2)其中,我希望事情会出错(如超时我只赶上方法例外)。
3)正如可读性的一个点,如果你有一个try catch块与在try部分一堆代码和闭锁段一堆,最好是代码提取到井命名的方法。
public void delete(Page page)
{
try
{
deletePageAndAllReferences(page)
}
catch (Exception e)
{
logError(e);
}
}
实际上,避免颗粒尝试/捕获。 允许例外在堆栈向上遍历和在尽可能高的水平尽可能被抓住。 如果你有一个值得关注的特定点,然后将在不久的捕捞记录,如果你担心例外级联 - 尽管你仍然可以通过钻入内部异常来解决这些。
异常处理不应该是一个事后的想法。 请确保你做到这一点始终。 我见过很多人把广阔的try / catch从开始到每一个方法的末尾,赶上一般例外。 人们认为这有助于他们获得更多的信息,而事实上,它没有。 更多的是在某些情况下少,因为少即是多。 我永远不会厌倦的公理的“例外应该被使用时要注意异常行为。” 恢复如果可以的话,尽量降低总体异常的数目。 没有比这更令人沮丧的,当你试图解决一个问题,看到数百个同NullReferenceException异常的或类似的,出问题的时候。
例外实现,使他们有没有成本,除非抛出。
这意味着,我认为表现后果不是针对一个有力的论据。 得天独厚的条件通常是...例外。