通常,当您处置私有(private)成员时,您可能会执行以下操作:
public void Dispose() {
var localInst = this.privateMember;
if (localInst != null) {
localInst.Dispose();
}
}
局部赋值的目的是避免竞争条件,即另一个线程可能在 null 检查后将私有(private)成员赋值为 null。在这种情况下,我不关心 Dispose
是否在实例上被调用了两次。
我一直使用这个模式,所以我写了一个扩展方法来做到这一点:
public static void SafeDispose(this IDisposable disposable)
{
if (disposable != null)
{
// We also know disposable cannot be null here,
// even if the original reference is null.
disposable.Dispose();
}
}
现在在我的类里面,我可以这样做:
public void Dispose() {
this.privateMember.SafeDispose();
}
问题是,FxCop 不知道我在做这件事,它给了我 CA2000: Dispose objects before losing scope在每种情况下都会发出警告。
我不想关闭此规则,也不想压制所有案例。有没有办法向 FxCop 暗示此方法就其而言等同于 Dispose
?
最佳答案
简短的回答是:没有办法暗示该对象正在别处处置。
一些 Reflector-ing(或 dotPeek-ing 或其他)解释了原因。
FxCop 在 C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop
. (根据您的 OS/VS 版本组合进行相应调整。)规则在 Rules
中。子目录。
主要FxCop
文件夹,打开
-
Microsoft.VisualStudio.CodeAnalysis.dll
-
Microsoft.VisualStudio.CodeAnalysis.Phoenix.dll
-
phx.dll
在Rules
文件夹,打开DataflowRules.dll
.
在DataflowRules.dll
查找 Phoenix.CodeAnalysis.DataflowRules.DisposeObjectsBeforeLosingScope
.这是进行评估的实际类。
查看其中的代码,您可以看到与您的问题相关的两件事。
- 它使用一个名为
SharedNeedsDisposedAnalysis
的共享服务. - 它来自
FunctionBodyRule
.
第一项很有趣,因为 SharedNeedsDisposedAnalysis
是什么决定了哪些符号需要 Dispose()
调用。 它非常彻底,“遍历”代码以确定需要处理的内容以及实际处理的内容。然后它会保留这些内容的表格以备后用。
第二项很有趣,因为 FunctionBodyRule
规则评估单个函数的主体。还有其他规则类型,例如 FunctionCallRule
评估函数调用成员之类的东西(例如 ProvideCorrectArgumentsToFormattingMethods
)。
重点是,在 SharedNeedsDisposedAnalysis
中潜在的“未命中”之间服务可能不会通过您的方法递归以查看实际正在处理的东西以及 FunctionBodyRule
的限制不超出函数体,它只是没有捕捉到您的扩展。
这与像 Guard.Against<ArgumentNullException>(arg)
这样的“守卫功能”的原因相同。在使用参数之前永远不会被视为验证参数 - FxCop 仍会告诉您检查参数是否为 null,即使这是“保护函数”正在做的事情。
您基本上有两个选择。
- 排除问题或关闭规则。它不可能按照您的意愿行事。
- 创建将理解扩展方法的自定义/派生规则。使用您的自定义规则代替默认规则。
在我自己编写自定义 FxCop 规则之后,我会让您知道我找到了它...非常重要。如果你真的走那条路,虽然世界上的建议是使用新的 Phoenix 引擎规则样式(这就是当前的 DisposeObjectsBeforeLosingScope
使用的),但我发现更容易理解旧的/标准的 FxCop SDK 规则(请参阅FxCopSdk.dll
在主 FxCop 文件夹中)。 Reflector 将在弄清楚如何做到这一点方面提供巨大帮助,因为它几乎没有文档。查看 Rules
中的其他程序集文件夹以查看这些示例。
关于c# - 告诉 FxCop 另一个方法正在调用 dispose,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11249584/