何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 761
  • 記事 - 18
  • コメント - 36019
  • トラックバック - 222
ニュース
  • IE7以前では、表示がおかしい。div の解釈に問題があるようだ。
    IE8の場合は、「互換」表示を OFF にしてください。
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2011
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 

2012年3月30日

前のエントリで、aetosさんからコメントを頂きました。

一般論として、CA1063 や CA1816 を抑止するのは不穏な臭いが。

はい、確かに、その通りです。

抑止したい、具体的なコードを示します。まず、MSDN のドキュメントから。

アンマネージ リソースをクリーンアップするための Finalize および Dispose の実装(msdn)より:

Dispose メソッド名のカスタマイズ

場合によっては、Dispose ではなく、ドメイン固有の名前を付ける方が適切なこともあります。たとえば、ファイルのカプセル化では、メソッド名として Close を使用した方が適切です。この場合は、Dispose をプライベートに実装し、Dispose を呼び出すパブリックな Close メソッドを作成します。

この、「Dispose メソッド名のカスタマイズ」を行います。新規にクラス ライブラリ プロジェクトを作成し、次のコードを書きます。

// Dispose メソッド名をカスタマイズしたクラス
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Practice16
{
    public class Class1 : IDisposable
    {
        private IntPtr handle;
        private Stream file;

        ~Class1()
        {
            this.Dispose(false);
        }

        public void Open(string fname)
        {
            // ハンドルを獲得
            this.handle = Marshal.AllocHGlobal(1024);
            file = new FileStream(fname, FileMode.Open);
        }

        public void Close()
        {
            ((IDisposable)this).Dispose();
        }

        //public void Close()
        //{
        //    this.Dispose(true);
        //    GC.SuppressFinalize(this);
        //}

        protected virtual void Dispose(bool disposing)
        {
            if (disposing == true)
            {
                // マネージ オブジェクトで
                // 破棄が必要なものを破棄
                file.Close();
            }

            // ハンドルを破棄
            Marshal.FreeHGlobal(this.handle);
            handle = IntPtr.Zero;
        }

        #region IDisposable メンバ

        void IDisposable.Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        //void IDisposable.Dispose()
        //{
        //    this.Close();
        //}

        #endregion
    }
}

このコードを FxCop に通すと、次のエラーが出ます。

CA2210
アセンブリに署名していないため。
CA1014
アセンブリが CLS 互換性があるとマークされていないため。
CA1063
IDisposable インターフェイスを実装しながら public void Dispose() メソッドがないため。
CA2122
Dispose(bool) メソッドで Marshal.FreeHGlobal(IntPtr) メソッドを使用しているが、セキュリティ チェックが行われていないため。
CA2122
Open(String) メソッドで Marshal.AllocHGlobal(int) メソッドを使用しているが、セキュリティ チェックが行われていないため。

CA1816 は、Close() メソッドと Dispose メソッドの明示実装をコメントアウトしているような実装にしていたからで、これは、直しました。

この様に、メソッド名をカスタマイズすると、FxCop はかなり強い警告を表示します。明示実装があるんだから堪忍して欲しい。それとも、Close()Dispose() の両方を置く?

posted @ 23:34 | Feedback (93)