为啥 FxCop 坚持使用 IDisposable 作为结构
Posted
技术标签:
【中文标题】为啥 FxCop 坚持使用 IDisposable 作为结构【英文标题】:Why does FxCop insist on IDisposable for a struct为什么 FxCop 坚持使用 IDisposable 作为结构 【发布时间】:2012-11-07 19:59:27 【问题描述】:我的一个项目中有类似于以下的代码:
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
,但这似乎是错误的。同样,我可以简单地抑制警告,但目前,我想了解触发警告的这个特定结构是什么,当它与我在同一个源文件中的其他七个结构没有太大不同时。或者,我很乐意接受解释为什么其他结构不触发此警告。
【问题讨论】:
只是禁止警告,除非你是分配非托管句柄的人,在这种情况下你应该实现 IDisposable。 我意识到我可以简单地抑制警告,但我想了解是什么让 this 结构如此特别。我将编辑问题以明确表示我不想在这种情况下禁止显示警告。 您能否发布另一个同样具有 IntPtr 且不会触发 FxCop 警告的结构的代码? @Scott 完成最新编辑。 【参考方案1】:只要您的托管类型包含它认为是“本机”类型的成员,Code Anylsis 引擎就会生成此警告。要成为原生类型,该字段必须:
成为IntPtr
、UIntPtr
或HandleRef
不是static
实际上是从本机代码中赋值的
我很确定这第三个项目符号可能是您的各种结构之间的区别。分析引擎(基于对 dotPeek 的快速阅读)只有在实际发现您的 IntPtr
的实例是从本机代码分配时才会触发警告。我还没有找到它所认为的“来自本机代码的赋值”的确切内容,但不管是什么,我最好的猜测是你们中只有一个不同的struct
类型正在触发这部分规则。
请注意,这是基于读取 VS2010 附带的代码分析引擎的当前实现的实际代码。这绝对是不是记录在案的规则行为,而可能是减少误报的特定优化。您不应假设当前“通过”此规则的代码(例如,因为它从未从本机代码分配)将始终这样做,因为 MS 可以随时更改实现细节。
正如我在评论中提到的,在这种情况下,隐藏消息是完全合法的回应;这不是不应禁止的 FxCop 规则之一。该规则是非常特定于上下文的,并且仅在您分配您自己的本机资源时适用。如果您只是在 C# 和非托管代码之间来回传递结构,那么您很可能只是取消警告并继续前进。
【讨论】:
就是这样,实际上是从本机代码分配的。我忘记阅读哪些文档页面,这些项目符号的布局位置? 他们不是。我在代码分析程序集上运行了 dotPeek 并对其进行了跟踪。我应该在回答中指出这一点。 警告将应用于结构似乎很奇怪,因为结构不可能真正“拥有”任何东西。分析引擎记录包含此类类型的结构是有意义的,并建议任何包含这些结构类型字段的类都应实现IDisposable
,但具有结构类型包括@987654328 的非平凡实现@ 似乎是一个非常严厉的反模式。【参考方案2】:
在您链接的文章中已经清楚地说明了这一点:
此规则假定 IntPtr、UIntPtr 和 HandleRef 字段存储指向非托管资源的指针。分配非托管资源的类型应该实现 IDisposable 以让调用者按需释放这些资源并缩短持有资源的对象的生命周期。
因此,仅 IntPtr 在结构中的简单外观就足以触发警告。在您确认您真的没有忘记释放本机资源后,在结构上应用 [SuppressMessage] 属性,不必再次查看此消息。
【讨论】:
但这正是我的观点。在同一个项目中,我实际上有七个其他结构,其中五个还包含IntPtr
成员。它们都不会触发相同的警告。是的,我阅读了文档;不,我不明白一个结构如何触发警告,但其他结构不会。以上是关于为啥 FxCop 坚持使用 IDisposable 作为结构的主要内容,如果未能解决你的问题,请参考以下文章
本地使用的 IDisposable 是不是有 FxCop 规则?
FxCop(/VS2010 代码分析),可以将方法结果标记为 IDisposable 的“现在调用者责任”吗?