4

プロジェクトの 1 つに次のようなコードがあります。

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が、それは間違っているようです。同様に、単純に警告を抑制することもできますが、現時点では、同じソース ファイルにある他の 7 つの構造体とそれほど変わらないときに、この特定の構造体が警告をトリガーしている理由を理解したいと考えています。または、他の構造体がこの警告をトリガーしない理由の説明を喜んで受け入れます。

4

2 に答える 2

7

Code Anylsisエンジンは、「ネイティブ」タイプと見なされるメンバーを含むマネージドタイプがある場合は常にこの警告を生成します。ネイティブタイプであるためには、フィールドは次の条件を満たしている必要があります。

  • 、、またはIntPtr_UIntPtrHandleRef
  • しないでくださいstatic
  • 実際にはネイティブコードから値が割り当てられます

この3番目の箇条書きは、おそらくさまざまな構造の違いであると確信しています。分析エンジン(簡単なdotPeekの閲覧に基づく)は、IntPtrネイティブコードから割り当てられているインスタンスを実際に検出した場合にのみ、警告をトリガーします。struct「ネイティブコードからの割り当て」と見なされるものを正確に見つけることはまだできていませんが、それが何であれ、さまざまなタイプがルールのその部分をトリガーしているのは1人だけだと思います。

これは、VS2010に付属しているコード分析エンジンの現在の実装の実際のコードを読み取ることに基づいていることに注意してください。これは、ルールの文書化された動作ではありませんが、誤検知を減らすための特定の最適化である可能性があります。MSはいつでも実装の詳細を自由に変更できるため、現在このルールを「通過」しているコード(たとえば、ネイティブコードから割り当てられていないため)が常に通過すると想定しないでください。

私のコメントで述べたように、この場合、メッセージを抑制することは完全に正当な応答です。これは、決して抑制されるべきではないFxCopルールの1つではありません。このルールは非常にコンテキスト固有であり、独自のネイティブリソースを割り当てる場合にのみ適用されます。C#とアンマネージコードの間で構造体をやり取りするだけの場合は、警告を抑制して先に進むことができます。

于 2012-11-07T20:18:31.923 に答える
2

あなたがリンクした記事でそれは非常に明確に説明されています:

このルールは、IntPtr、UIntPtr、およびHandleRefフィールドがアンマネージリソースへのポインターを格納することを前提としています。管理されていないリソースを割り当てるタイプは、IDisposableを実装して、呼び出し元がそれらのリソースをオンデマンドで解放し、リソースを保持するオブジェクトの有効期間を短縮できるようにする必要があります。

したがって、構造体でのIntPtrの単純な外観だけで、警告をトリガーするのに十分です。ネイティブリソースを解放することを本当に忘れていないことを確認したら、構造体に[SuppressMessage]属性を適用して、このメッセージを再度確認する必要がないようにします。

于 2012-11-07T20:12:44.293 に答える