どういうこと?
WININET.DLLの外部メソッド呼び出しで使用されるハンドルのラッパークラスを定義します。
どうして?
IDisposableをインプリメントするので、using句を使えばハンドルの解放漏れがなくなります。
どうすれば?
ソースコードを記載します。
using System; using System.Runtime.InteropServices; namespace Shared.Net { /// <summary> /// WININET.DLLの外部メソッド呼び出しで使用されるハンドル /// (<see cref="System.IntPtr"/>)をラップします。 /// </summary> public class InternetHandle : IDisposable { [DllImport("WININET", EntryPoint = "InternetCloseHandle", SetLastError = true, CharSet = CharSet.Auto)] static extern bool InternetCloseHandle(IntPtr hInternet); /// <summary> /// ハンドルが0かどうかを示します。 /// </summary> /// <value>ハンドルが0で初期化されている場合はtrue。それ以外はfalse。</value> public bool IsZero { get { return this.pointer == IntPtr.Zero; } } /// <summary> /// このクラスの内部で保持しているハンドルです。 /// </summary> /// <value>ハンドルが0の場合は無効なハンドル、それ以外の場合は有効なハンドルです。</value> public IntPtr Pointer { get { return this.pointer; } } IntPtr pointer = IntPtr.Zero; /// <summary> /// InternetHandleクラスの新しいインスタンスを初期化します。 /// </summary> /// <param name="pointer">ハンドル</param> public InternetHandle(IntPtr pointer) { this.pointer = pointer; } #region 終了処理 /// <summary> /// ガベージ コレクションによってクリアされる前に、アンマネージ リソースを解放し、 /// その他のクリーンアップ操作を実行します。 /// </summary> ~InternetHandle() { Dispose(); } /// <summary> /// 既にDisposeが呼ばれたかどうかを示します。 /// </summary> /// <value>既にDisoseが呼ばれた場合はtrue。まだ呼ばれていない場合はfalse。</value> public bool Disposed { get { return this.disposed; } } private bool disposed = false; /// <summary> /// アンマネージ リソースの解放および終了処理を実行します。 /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// アンマネージ リソースの解放および終了処理を実行します。 /// </summary> /// <param name="disposing"> /// マネージ リソースとアンマネージ リソースの両方を解放する場合は true。 /// アンマネージ リソースだけを解放する場合は false。 /// </param> private void Dispose(bool disposing) { if (disposed) return; // アンマネージリソースを解放する。 if (this.IsZero) InternetHandle.InternetCloseHandle(this.pointer); this.pointer = IntPtr.Zero; disposed = true; } #endregion 終了処理 } }