我在项目中使用静态代码分析来检查代码违规。其中一个广泛使用的规则是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
}
还有其他人遇到过这种行为吗?这是CA2213规则中的设计还是错误?
答案 0 :(得分:4)
代码分析器确实有局限性,此代码中的代码分析器需要生成可操作的警告。一个程序员可以实际跟进来修复他的代码。当前代码分析器的一个关键问题是它不分析源代码,它可以从编译器生成的程序集中工作。哪个好,适用于任何.NET语言。但没有人会喜欢这个警告:
CA2213应处置一次性字段
&#39;坏&#39;包含IDisposable类型的字段<Font>k__BackingField
:&#39;字体&#39;。在&#39; Bad&#39;上更改Dispose方法在此字段上调用Dispose或Close。
Yikes,当然程序中没有这样的字段。为了生成更好的消息,分析器必须确定元数据中的<Font>k__BackingField
字段实际上与自动实现的Font
属性相关联。元数据中没有任何内容可以明确地建立连接。该字段仅携带[CompilerGenerated]属性,自动生成的字段名称是编译器实现细节。不同的语言编译器生成不同的名称。
这是一种需要源代码分析的问题,而不是目前实施的IL分析。机会正在敲门,今天Roslyn可以更容易地实现源代码分析。 VS2015是第一个支持&#34; Live Code&#34;的VS版本。分析。我不知道它是否会很快找到CA2213样式错误。
答案 1 :(得分:0)
静态分析工具经过精心调整,可以在生成过多的误报(即在完美的代码上发出问题)和过多的假阴性(即代码中缺少实际问题)之间进行良好的权衡。
我们举一个简单的例子:
// CA2213 detects an issue
class OwnsTheField : IDisposable
{
private MemoryStream f = new MemoryStream();
public void Dispose() {}
}
在这种情况下很明显应该报告一个问题,事实确实如此。
现在,让我们稍微复杂一点:
// CA2213 does not detect
class FieldIsInjected : IDisposable
{
private MemoryStream f;
public FieldIsInjected(MemoryStream p)
{
f = p;
}
public void Dispose() { }
}
在这种情况下,可能不存在不处理f
的问题。如果调用者正确处理p
,那么一切都按预期工作:
using (var p = new MemoryStream())
{
using (var x = FieldIsInjected(p)) { /* ... */ }
} // p is properly disposed
通常情况下,不会记录确切的行为(包括处理所有极端情况),因为详尽的文档在一段时间内维护成本太高。例如,https://msdn.microsoft.com/en-us/library/ms182328.aspx
中明确提到了此异常答案 2 :(得分:0)
规则来自.net framework 2和auto properties are from C# 3,它是在创建规则后添加到语言规范中的。规则是根据字段而不是属性来定义的,因此它似乎应该更新,但是按照当前指定的方式工作。
This Question on disposing properties似乎表明实现IDisposable
的属性在框架中不一致。
答案 3 :(得分:0)
分析引擎完全能够在物业及其支持场之间行走。它只是没有逻辑去做,因此错过了发出警告的机会。更糟糕的是,如果正确处置的属性是get-only,则会发出false warning。