C#/.NET中的方法自动记录异常

32

我想要一些工具,最好是可以插入到VS 2008/2010中的,能够遍历我的方法并添加关于可能引发的异常的XML注释。 我不希望为我生成<summary>或其他XML标记,因为我将自己填写这些内容,但如果即使在私有/受保护的方法中,我也可以看到可能会被抛出的异常列表,那就太好了。否则,我会逐个查看方法并悬停在其中的所有方法调用上以查看异常列表,然后更新该方法的<exception>列表以包括它们。也许可以使用VS宏来完成此操作?

private static string getConfigFilePath()
{
    return Path.Combine(Environment.CurrentDirectory, CONFIG_FILE);
}

转为:

/// <exception cref="System.ArgumentException"/>
/// <exception cref="System.ArgumentNullException"/>
/// <exception cref="System.IO.IOException"/>
/// <exception cref="System.IO.DirectoryNotFoundException"/>
/// <exception cref="System.Security.SecurityException"/>
private static string getConfigFilePath()
{
    return Path.Combine(Environment.CurrentDirectory, CONFIG_FILE);
}

更新: 看起来这个工具需要递归地遍历方法,例如,方法1调用方法2,方法2又调用方法3,而方法3被记录为抛出 NullReferenceException,因此该工具将记录方法1和方法2也会抛出 NullReferenceException。该工具还需要消除重复项,例如,如果方法中的两个调用都被记录为抛出 DirectoryNotFoundException,则该方法只会列出一个 <exception cref="System.IO.DirectoryNotFoundException"/>


4
请注意,这样的工具并不简单,并且永远无法保证给出一个完整的异常列表,因为a) 代码可能会使用反射等动态执行,或者b) 异常由运行时引发,例如OutOfMemoryException、StackOverflowException等。 - Dirk Vollmar
2
这也不可能是详尽无遗的,因为这样的工具必须同时处理所有可能的托管异常,包括BCL中的异常,并且可能需要了解与Interop相关的底层COM异常。 - Oded
2
我很好奇你为什么想这样做。如果不知道可能会抛出哪些异常,对你的调用代码有什么影响呢? - Christian Hayter
5
@Christian Hayter: 对于用户来说,了解会出现哪些异常情况是很有帮助的。例如,MSDN 就有这方面的文档记录。 - Dirk Vollmar
1
@FrustratedWithFormsDesigner:严格来说,这对于每个(本地的,意味着没有服务引用).NET程序集都是正确的。即使是混淆的IL也可以被分析(实际上,它可以在没有任何额外困难的情况下被分析)以进行异常处理。 - Adam Robinson
显示剩余3条评论
4个回答

10
长话短说,这是不可能的。与Java不同,.NET语言中没有要求函数报告可能抛出的异常列表的规定(这意味着你必须捕获或报告它调用的任何函数可能抛出的异常)。因此,没有通用的方法可以确定一个函数可能引发的所有异常的详尽列表(我在这里使用“函数”一词来涵盖任何像函数一样编写的内容,包括运算符、构造函数等),因为您不能保证特定函数调用可能引发哪些异常。
如果你愿意做有限的事情,那么可以想象你可以编写一些代码来扫描MSDN上针对给定.NET库调用的适当文章,并使用那里列出的异常列表(如果有的话)来递归地建立可能被抛出的异常列表。但是,这不会覆盖任何第三方库,也无法捕获运行时抛出的任何异常(例如OutOfMemoryException,StackOverflowException,NullReferenceException[除非你想进一步进行异常分析并确定是否存在空引用的可能性,但这似乎在完全通用的意义上也不可能)。
我相信C#团队已经讨论过这个问题了(我会感到惊讶如果Eric Lippert还没有在SO上回答过这个问题),但我很确定结论是:虽然这种系统对于某些人来说很有用和有价值,但强制使用它(并迫使您报告或捕获所有可能抛出的异常)会导致大量的try {...} catch (Exception ex) {...}块为了避免繁琐的工作,而笼统的、静默的catch要比未报告异常更糟糕(依我之见)。

2
仅递归检查注释的问题在于您不知道顶部方法catch()捕获了哪些异常。因此,如果A调用B,而B可以抛出各种异常,您不知道这些异常是向上冒泡还是被捕获。任何静态分析都将毫无用处,除非您了解确切的基础代码。因此,如果您这样做,请不要费心递归查找;您必须相信方法A()会正确记录可能引发的所有异常。 - drharris
2
一个人不可能简单地递归检查方法注释。他们的黑色XML受到更多东西的保护,而不仅仅是catch块。那里有一种不会睡觉的邪恶存在。 - Sarah Vessels
@drharris:虽然你是正确的,但我不确定你的意思是什么。如果没有访问底层代码,你怎么可能进行递归检查呢?即使你通过IL分析而不是源代码来分析它,你仍然可以确定捕获了哪些异常。虽然我认为我们在这个问题上达成了一致(以及在完全通用的情况下可能是不可能的),但我不清楚如何在没有访问代码的情况下递归地分析代码。 - Adam Robinson
@Adam Robinson:我认为drharris在谈论代码时指的是IL。如果没有IL(或源代码),只有XML注释,你将无法知道哪些异常已经被处理了。 - Dirk Vollmar
1
OP在更新部分提到了递归分析。我只是想指出,递归分析不会产生一个正确的指示哪些异常通过而不需要一个非常广泛的算法(和IL访问)。而且仅凭XML注释,你无法确定从被调用命令中传递了什么。这是一个意识点,任何工具都不会是100%准确的。 - drharris
显示剩余5条评论

2

1

Exception Hunter来自RedGate软件,可以帮助您解决一半的问题。它可以对您的代码进行静态分析,并显示哪些代码行将抛出异常,包括.NET Framework调用。但它不会为您编写XML文档。

但是,我必须说,您需要对这样的工具有多大用处保持现实态度...有许多异常可能是由极其不寻常的情况引起的,例如System.OutOfMemoryExceptionSystem.ExecutionEngineException,或者由于程序员错误而引起,例如System.NotImplementedException。从技术上讲,这些都是可能的,但从实际角度考虑,试图为每个方法记录大多数异常并不值得您的时间...您最终会为应用程序中几乎每个方法编写数百行注释。


异常捕获器已经停止更新。 - uli78

0

RedGate 异常猎手可以分析代码中可能会出现的异常情况。或许您可以使用其中的一些功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接