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

时间:2009-01-20 13:39:28

标签: c# .net documentation intellisense

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

我想提供良好的智能感知信息,但我不确定如何来记录抛出的异常。

在以下示例中:

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()引发的异常吗?

记录可能的例外的最佳方法是什么?

8 个答案:

答案 0 :(得分:106)

您应记录代码可能抛出的每个异常,包括您可能调用的任何方法中的异常。

如果列表有点大,您可能想要创建自己的异常类型。抓住你在方法中可能遇到的所有问题,将它们包装在异常中,然后抛出它。

您可能想要这样做的另一个地方是,如果您的方法是在API的表面上。就像外观将多个接口简化为单个接口一样,您的API应将多个异常简化为单个异常。使呼叫者更容易使用您的代码。


为了回答安德鲁的一些担忧(来自评论),有三种类型的例外:你不知道的,你知道但不能做任何事情,以及你知道和可以做的事情。一些关于。

你不了解的人想要放手。它是快速失败的原则 - 更好地使您的应用程序崩溃,而不是进入可能最终破坏您的数据的状态。崩溃将告诉你发生了什么以及为什么,这可能有助于将这个异常移出“你不知道的”列表。

你知道但不能做任何事情的是像OutOfMemoryExceptions这样的例外。在极端情况下,您可能希望处理这样的异常,但除非您有一些非常出色的要求,否则您将它们视为第一类 - 让我们去吧。您来记录这些例外情况吗?对于新建对象的每一种方法,你都会看起来非常愚蠢地记录OOM。

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

您可以找到更多guidelines on exception handling here.

答案 1 :(得分:91)

您应该使用standard xml documentation

/// <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.");
    }
}

这样做的价值在于您提供了可能发生的已知异常的文档。如果您使用visual studio,则可以在intellisense中获得此文档,并且可以在以后提醒您(或其他人)您可以预期的异常。

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

答案 2 :(得分:34)

通过使用几个出色的加载项,您可以简化文档编制过程。其中一个是GhostDoc,它是Visual Studio的免费加载项,可生成XML-doc注释。此外,如果您使用ReSharper,请查看ReSharper的优秀Agent Johnson Plugin,它会添加一个选项来为抛出的异常生成XML注释。

更新:似乎Agen Johnson不适用于R#8,结帐Exceptional for ReSharper作为替代方案......

  

步骤1:GhostDoc生成XML   评论(Ctrl-Shift-D),同时代理约翰逊插件   对于ReSharper建议记录   例外:

step 1

  

第2步:使用ReSharper的快捷键   (Alt-Enter)添加例外   文档:

step 2 http://i41.tinypic.com/osdhm

希望有所帮助:)

答案 3 :(得分:10)

据我所知,使用&lt; exception&gt;的意图element是在装饰方法时使用它,而不是例外:

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

应该在这些方法中捕获,处理和记录被调用的其他方法可能抛出的异常。可能会记录.NET可能引发的异常,或者由您自己的代码引发显式的异常。

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

答案 4 :(得分:4)

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

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 可能被抛出等等。

答案 5 :(得分:1)

您应该记录您的方法可能抛出的所有异常。

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

如果您无法处理或解决异常,您可以考虑重新启用它们。大多数打包/包装在调用者的更有意义的例外中。

答案 6 :(得分:1)

事实上,正如已经回答的那样,记录异常的方法是使用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

问候。

答案 7 :(得分:0)

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

请记住,这是告诉来电者期待什么,以便他们可以选择如何处理。