如何在 c #/. net 中记录抛出的异常

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

我想提供良好的智能感知信息,但我不确定 怎么做文档抛出的异常。

例如:

public void MyMethod1()
{
MyMethod2();


// also may throw InvalidOperationException
}


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


// also may throw DivideByZeroException
}

我知道记录异常的标记是:

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

我不明白的是如何记录由代码 打来的 MyMethod1()抛出的异常?

  • 我应该记录由 MyMethod2()抛出的异常吗
  • 我应该记录由 File.Open()抛出的异常吗?

记录可能的异常的最佳方式是什么?

61898 次浏览

您应该记录所有可能由您的方法引发的异常。

为了隐藏实现细节,我将尝试自己处理 MyMethod2中的一些异常。

如果不能处理或解决异常,可以考虑回退它们。通常打包/包装在一个对调用者更有意义的异常中。

在您的方法中记录预期的异常,在您的示例中,我会让用户知道该方法可以抛出未找到异常的文件。

记住,这是为了告诉打电话的人要期待什么,这样他们就可以选择如何处理它。

根据我的理解,使用 < Exception > 元素的目的是在修饰方法时使用它,而不是在修饰异常时使用它:

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

应该在这些方法中捕获、处理和记录可由调用的其他方法引发的异常。可能抛出的例外。NET,或者由您自己的代码引发的 明确地异常应该被记录下来。

至于获得更多的具体信息,也许您可以捕获并抛出自己的定制异常?

你应该使用 标准的 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.");
}
}

这样做的价值在于,您提供了可能发生的已知异常的文档。如果您正在使用可视化工作室,这个文档是智能意义上的,并且可以在以后提醒您(或其他人)可以预期的异常。

您需要指定特定的异常类型,因为您可能能够处理一种类型的异常,而其他类型是严重问题的结果,无法纠正。

应该记录代码可能引发的每个异常,包括可能调用的任何方法中的异常。

如果列表有点大,您可能需要创建自己的异常类型。捕获在方法中可能遇到的所有异常,将它们包装在异常中,然后抛出该异常。

您可能希望这样做的另一个地方是,如果您的方法位于 API 的表面上。正如 facade 将多个接口简化为单个接口一样,您的 API 应该将多个异常简化为单个异常。使呼叫者更容易使用您的代码。


为了回答安德鲁的一些担忧(来自评论) ,有三种类型的例外: 一种是你不知道的,一种是你知道但是无能为力的,还有一种是你知道但是可以做些什么的。

那些你不了解的人,你想放手。这就是快速失败的原则——最好让你的应用程序崩溃,而不是进入一个可能最终导致数据损坏的状态。崩溃会告诉你发生了什么以及为什么,这可能有助于将异常从“你不知道的”列表中移除。

那些您知道但是无法处理的异常是像 OutOfMemory 异常这样的异常。在极端的情况下,您可能希望处理这样的异常,但是除非您有一些非常显著的需求,否则您可以像对待第一类一样对待它们——让它们去吧。是否用 记录这些异常?在每一个新建对象的方法上记录 OOM 会显得很愚蠢。

那些你知道并且可以做些什么的,就是你应该记录和包装的。

你可以找到更多的 异常处理指南。

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

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
}

使用这种方法,可以更容易地记录显式抛出的所有异常,而不必记录抛出 OutOfMemoryException 也许吧的异常,等等。

通过使用几个很棒的外接程序,可以使您的文档处理过程更加简单。其中之一是 GhostDoc,这是 VisualStudio 的一个免费外接程序,可以生成 XML-doc 注释。另外,如果您使用 锐利者,那么可以看一下针对 ReSharper 的优秀的 Johnson Plugin 探员,它添加了一个选项来为抛出的异常生成 XML 注释。

更新: 似乎阿根廷约翰逊没有为 R # 8,检查 ReSharper 是个例外作为一个替代..。

步骤1: GhostDoc 生成 XML 注释(Ctrl-Shift-D) ,而代理约翰逊插件 ReSharper 建议记录 也有例外:

step 1

步骤2: 使用 ReSharper 的快捷键 (Alt-Enter)添加异常 文件:

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

希望这能有所帮助:)

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

除了插件之外,您还可以使用可以与 TFS 集成的静态分析工具,以确保记录了异常。

在下面的链接中,您可以看到如何为 StyleCop 构建一个自定义规则,以验证您的方法引发的异常。

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-exceptions-ii.aspx

问候。