4

我的同事们都是经验丰富的 C++ 黑客,他们转而使用 .Net。他们无意中犯的错误之一是编写如下代码:

catch(ArgumentExcepttion ae)
{
    // Code here logs the exception message
    // And this is supposed to re-throw the exeception
    throw ae; // as opposed to throw;
    // But, as we all know, doing this creates a new exception with a shorter stack trace.
}

我在很多地方都看到过这种做法。我真的想不出切断堆栈跟踪有用的情况。我认为这应该是值得评论的特殊情况。如果我错了,请纠正我。如果要剪切堆栈跟踪,我认为最好这样做:

throw new ArgumentException("text", ae /* inner exc */);

无论如何,我想做的是检测所有此类情况并发出警告。正则表达式搜索没有帮助,因为:

catch(Exception e)
{
    Exception newExc = new Exception("text", e);
    Log(newExc);
    throw newExc;
}

我将不得不使用 StyleCop 之类的工具(我有,版本 4.3.3.0 )。我现在正在使用 VS2008,但很快就会切换到 VS2010。

关于如何完成我正在寻找的任何想法?

4

3 回答 3

5

FxCop 对此有一个规则: RethrowToPreserveStackDetails

一旦抛出异常,它携带的部分信息就是堆栈跟踪。堆栈跟踪是方法调用层次结构的列表,它以引发异常的方法开始,以捕获异常的方法结束。如果通过在 throw 语句中指定异常而重新引发异常,则堆栈跟踪将在当前方法处重新启动,并且在引发异常的原始方法与当前方法之间的方法调用列表将丢失。要将原始堆栈跟踪信息与异常一起保留,请使用 throw 语句而不指定异常。

我相信 VS2010 内置了 FxCop 分析,但我不是 100% 确定...

这是FxCop 的 Microsoft 下载链接

于 2010-05-14T16:00:07.260 回答
1

代码是否不必要地捕获异常?如果您只对记录异常感兴趣,那么您只需要在代码的顶层捕获(在您可以进行记录的最后一个可能点)。这可能会严重减少您必须担心的捕获数量。

于 2010-05-14T15:58:49.553 回答
1

我建议寻找以 throw 结尾的 catch-blocks ...; 而不是以 throw; 结尾。

尽管您会得到一些误报,但您可以手动将它们过滤掉。

于 2010-05-14T15:59:04.520 回答