前のエントリで、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()
の両方を置く?
投稿日時 : 2012年3月30日 23:34