为什么FxCop坚持使用IDisposable作为结构

时间:2012-11-07 19:59:28

标签: c# fxcop

我的一个项目中的代码类似于以下代码:

internal enum ArtworkType
{
    Undefined = 0,
    Bmp = 1,
    Gif = 2,
    Jpeg = 3,
    Png = 4
}

[StructLayout(LayoutKind.Sequential)]
internal struct TagArtwork
{
    internal IntPtr data;
    internal int size;
    internal ArtworkType type;
}

当我在这段代码上运行FxCop时,我会遇到警告CA1049。此结构用于与本机代码库的互操作性,因此几乎 具有此布局。为什么FxCop让我对这个结构感到悲伤?我在同一个源文件中有其他结构,也有IntPtr个成员,但FxCop并不抱怨这些结构。

例如,以下代码会触发相同的警告:

internal enum ItemType
{
    Implicit = 0,
    Utf8 = 1,
    Utf16 = 2,
    Sjis = 3,
    Html = 6,
    Xml = 7,
    Uuid = 8,
    Isrc = 9,
    Mi3p = 10,
    Gif = 12,
    Jpeg = 13,
    Png = 14,
    Url = 15,
    Duration = 16,
    DateTime = 17,
    Genres = 18,
    Integer = 21,
    Riaa_pa = 24,
    Upc = 25,
    Bmp = 27,
    Undefined = 255
}

[StructLayout(LayoutKind.Sequential)]
internal struct MP4ItmfData
{
    internal byte typeSetIdentifier;
    internal ItemType typeCode;
    internal int locale;
    internal IntPtr value;
    internal int valueSize;
}

我想我可以在结构上实现IDisposable,但这似乎是错误的。同样,我可以简单地抑制警告,但此时,我想了解触发警告的这个特定结构是什么,当它与我在同一源文件中的其他七个结构没有那么大的不同。或者,我很乐意接受一个解释为什么其他结构会触发此警告。

2 个答案:

答案 0 :(得分:7)

Code Anylsis引擎会在您拥有包含其认为是“本机”类型的成员的托管类型时生成此警告。要成为本机类型,该字段必须:

  • IntPtrUIntPtrHandleRef
  • 不是static
  • 实际上是从本机代码中分配了一个值

我很确定这第三个子弹可能是你的各种结构之间的差异。分析引擎(基于快速dotPeek perusal)仅在实际发现从本机代码分配IntPtr的实例时才会触发警告。我还没有找到它认为“从本机代码中分配”的确切内容,但无论如何,我最好的猜测只是你们中的一个struct类型触发了规则的这一部分。

请注意,这是基于VS2010随附的代码分析引擎的当前实现的实际代码。绝对规则的记录行为,但可能是减少误报的特定优化。您不应该假设当前“通过”此规则的代码(例如,因为它从未从本机代码分配)将始终这样做,因为MS可以随时更改实现细节。

正如我在评论中所提到的,在这种情况下,压制消息是完全合法的回应;这不是永远不应该被压制的FxCop规则之一。该规则特定于上下文,仅在您分配您自己的本机资源时才适用。如果您只是在C#和非托管代码之间来回传递结构,那么您很可能只是禁止警告并继续前进。

答案 1 :(得分:2)

在您链接的文章中非常清楚地说明了这一点:

  

此规则假定IntPtr,UIntPtr和HandleRef字段存储指向非托管资源的指针。分配非托管资源的类型应实现IDisposable,以允许调用者按需释放这些资源,并缩短保存资源的对象的生命周期。

因此,结构中IntPtr的简单外观足以触发警告。在验证确实没有忘记释放本机资源后,在结构上应用[SuppressMessage]属性,不必再次查看此消息。