如何在c#/ .net中logging抛出的exception

我目前正在编写一个小的框架,供公司内其他开发人员内部使用。

我想提供良好的Intellisense信息,但是我不确定如何logging抛出的exception。

在以下示例中:

public void MyMethod1() { MyMethod2(); // also may throw InvalidOperationException } public void MyMethod2() { System.IO.File.Open(somepath...); // this may throw FileNotFoundException // also may throw DivideByZeroException } 

我知道loggingexception的标记是:

 /// <exception cref="SomeException">when things go wrong.</exception> 

我不明白的是如何logging MyMethod1() 调用的代码抛出的exception?

  • 我应该logging由MyMethod2()抛出的exception
  • 我应该loggingFile.Open()抛出的exception吗?

什么是logging可能的例外的最好方法?

你应该logging你的代码可能抛出的每个exception,包括你可能调用的任何方法中的exception。

如果列表有点大,您可能需要创build自己的exceptiontypes。 抓住你可能在你的方法中遇到的所有的东西,把它们包装在你的exception,并抛出。

另一个你可能想要这样做的地方是,如果你的方法是在你的API的表面上。 就像一个Facade将多个接口简化为一个接口一样,您的API应该将多个exception简化为一个exception。 使调用者更容易使用您的代码。


为了回答Andrew的一些担忧(从评论中),有三种types的例外情况:你不知道的,你知道的,不能做任何事的,你知道的,可以做的。

那些你不知道的你想放手。 它的快速失败的原因 – 更好的是你的应用程序崩溃,而不是进入最终会破坏数据的状态。 崩溃会告诉你发生了什么事情,为什么,这可能有助于将这个例外排除在“你不知道的事情”列表之外。

那些你知道的并且不能做任何事情的是exception,比如OutOfMemoryExceptions。 在极端的情况下,你可能想要处理像这样的exception,但是除非你有一些相当出色的要求,否则就把它们当作第一类 – 让我们走吧。 你必须logging这些例外吗? 你会看起来非常愚蠢的logging每一个新方法的对象的方法OOM​​s。

那些你知道的,可以做的事情是你应该logging和包装的。

你可以在这里find更多关于exception处理的指导。

您应该使用标准的xml文档 。

 /// <exception cref="InvalidOperationException">Why it's thrown.</exception> /// <exception cref="FileNotFoundException">Why it's thrown.</exception> /// <exception cref="DivideByZeroException">Why it's thrown.</exception> public void MyMethod1() { MyMethod2(); // ... other stuff here } /// <exception cref="FileNotFoundException">Why it's thrown.</exception> /// <exception cref="DivideByZeroException">Why it's thrown.</exception> public void MyMethod2() { System.IO.File.Open(somepath...); } /// <exception cref="FileNotFoundException">Why it's thrown.</exception> public void MyMethod3() { try { MyMethod2(); } catch (DivideByZeroException ex) { Trace.Warning("We tried to divide by zero, but we can continue."); } } 

这样做的价值在于您提供了可能发生的已知exception的文档。 如果您正在使用Visual Studio,并且可以在稍后提醒您(或其他人)可以预料到的例外情况,则可以在智能感知中使用此文档。

您要指定特定的exceptiontypes,因为您可能能够处理一种types的exception,而其他types是严重问题的结果并且不能被纠正。

通过使用几个优秀的插件,可以使您的文档处理变得更加简单。 其中之一就是GhostDoc ,它是Visual Studio的免费插件,可以生成XML-doc注释。 另外,如果您使用ReSharper ,请查看ReSharper优秀的Agent Johnson插件 ,该插件添加了一个用于为抛出的exception生成XML注释的选项。

更新:看来,阿让约翰逊是不可用的R#8,结帐例外ReSharper作为替代…

步骤1:GhostDoc生成XML注释(Ctrl-Shift-D),而ReSharper的Agent Johnson插件build议loggingexception:

第1步160wpb4.png

步骤2:使用ReSharper的快捷键(Alt-Enter)添加exception文档:

第2步http://i41.tinypic.com/osdhm

希望帮助:)

据我所知,使用<exception>元素的意图是在装饰方法时使用它,而不是例外:

 /// <summary>Does something!</summary> /// <exception cref="DidNothingException">Thrown if nothing is actually done.</exception> public void DoSomething() { // There be logic here } 

可以通过调用其他方法抛出的exception应该被捕获,处理并logging在这些方法中。 .NET可能抛出的exception,或者你自己的代码显式抛出的exception应该被logging下来。

就具体而言,也许你可以捕捉并抛出自己定制的exception?

你的方法的一部分合同应该是检查前提条件是否有效,所以:

 public void MyMethod2() { System.IO.File.Open(somepath...); // this may throw FileNotFoundException } 

 /// <exception cref="FileNotFoundException">Thrown when somepath isn't a real file.</exception> public void MyMethod2() { FileInfo fi = new FileInfo( somepath ); if( !fi.Exists ) { throw new FileNotFoundException("somepath doesn't exists") } // Maybe go on to check you have permissions to read from it. System.IO.File.Open(somepath...); // this may still throw FileNotFoundException though } 

通过这种方法,可以更容易地logging您明确抛出的所有exception,而不必logging可能抛出的OutOfMemoryException等。

你应该logging你的方法可能抛出的所有exception。

为了隐藏实现细节,我会尝试自己处理来自MyMethod2的一些exception。

如果您无法处理或解决exception情况,您可以考虑重新启用它们。 大多数情况下打包/打包在一个更有意义的例外调用者。

事实上,正如已经回答的那样,loggingexception的方法是使用XML注释。

除了插件之外,您还可以使用可以与TFS集成的静态分析工具,以确保您有例外logging。

在下面的链接中,您可以看到如何为StyleCop构build一个自定义规则来validation您的方法抛出的exception正在被logging。

http://www.josefcobonnin.com/post/2009/01/11/Xml-Documentation-Comments-Exceptions-I.aspx http://www.josefcobonnin.com/post/2009/01/15/Xml-Documentation -Comments-例外,II.aspx

问候。

在你的方法中logging预期的exception,在你的例子中,我会让用户知道,该方法可以抛出一个文件没有发现exception。

请记住,它是告诉调用者什么期望,以便他们可以select如何处理它。