Zvo*_*nko 15 c# dispose fxcop static-analysis
我在项目中使用静态代码分析来检查代码违规.其中一个广泛使用的规则是CA2213,它检查一次性场的正确处理.
我注意到CA2213没有检查处理自动实现的属性.
此外,如果类继承自实现IDisposable的类并且不覆盖Dispose方法,则CA2213不会检查是否处置字段或自动实现的属性.
实际例子:
public sealed class Good : IDisposable {
private Font font;
public Font Font {
get { return font; }
set { font = value; }
}
public Good() { font = new Font("Arial", 9); }
public void Dispose() { /* Do nothing */ } // CA2213
}
public sealed class Bad : IDisposable {
public Font Font { get; set; }
public Bad() { Font = new Font("Arial", 9); }
public void Dispose() { /* Do nothing */ } // No warning
}
Run Code Online (Sandbox Code Playgroud)
有没有其他人遇到过这种行为?这是CA2213规则中的设计还是错误?
代码分析器确实有局限性,此代码中存在的局限性在于它需要生成可操作的警告。程序员实际上可以跟进来修复其代码的代码。当前代码分析器的一个关键问题是它不分析源代码,而是通过编译器生成的程序集工作。很好,它适用于任何.NET语言。但是没有人会喜欢这个警告:
CA2213应处理一次性字段
“错误”包含<Font>k__BackingFieldIDisposable类型的字段:“字体”。将“不良”上的Dispose方法更改为在此字段上调用Dispose或Close。
当然,程序中没有这样的领域。为了生成更好的消息,分析器必须确定<Font>k__BackingField元数据中的字段实际上与自动实现的Font属性相关联。元数据中没有任何可用内容可以明确地建立连接。该字段仅包含[CompilerGenerated]属性,并且自动生成的字段名称是编译器实现的详细信息。不同的语言编译器生成不同的名称。
这类问题需要源代码分析,而不是当前实施的IL分析。机会来了,如今,使用Roslyn可以更轻松地实现源代码分析。VS2015是第一个支持“实时代码”分析的VS版本。我尚不知道它是否会很快发现CA2213样式错误。
静态分析工具经过调整,可以在生成太多误报(即在完美的代码上发出问题)和太多漏报(即在代码中遗漏真正的问题)之间进行良好的权衡。
让我们举一个简单的例子:
// CA2213 detects an issue
class OwnsTheField : IDisposable
{
private MemoryStream f = new MemoryStream();
public void Dispose() {}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,很明显应该报告一个问题,事实也确实如此。
现在,让我们把事情变得稍微复杂一些:
// CA2213 does not detect
class FieldIsInjected : IDisposable
{
private MemoryStream f;
public FieldIsInjected(MemoryStream p)
{
f = p;
}
public void Dispose() { }
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,不处理可能不会有问题f。如果p调用者正确处理,那么一切都会按预期进行:
using (var p = new MemoryStream())
{
using (var x = FieldIsInjected(p)) { /* ... */ }
} // p is properly disposed
Run Code Online (Sandbox Code Playgroud)
通常,确切的行为(包括所有极端情况的处理)不会被记录下来,因为随着时间的推移,详尽的文档的维护成本太高。例如,https://msdn.microsoft.com/en-us/library/ms182328.aspx中明确提到了此异常
| 归档时间: |
|
| 查看次数: |
1716 次 |
| 最近记录: |