4

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

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

4

2 回答 2

7

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

  • IntPtr, UIntPtr, 或HandleRef
  • 不是static
  • 实际上从本机代码中分配了一个值

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

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

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

于 2012-11-07T20:18:31.923 回答
2

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

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

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

于 2012-11-07T20:12:44.293 回答