2009年12月03日

FxCopに学ぶ番外編(7) : Dispose メソッドから基本クラスの破棄を呼び出します

   このエントリーをはてなブックマークに追加 Clip to Evernote

メールマガジン「C#プログラミングレッスン」では、今、[FxCopに学ぶ編] を連載中です。
そこで取上げようとしたルールで、下書きまでしたのですが、結局メルマガには書かないことにしたルールがいくつかあります。
そのまま捨ててしまうのはもったいないので、ブログに掲載します。


■IDisposableの実装(3)■

「CA2215:Dispose メソッドから基本クラスの破棄を呼び出します」
というルールがあるのですが、どのようなコードを書いたらこの FxCopの警告が出るのが試したのですが、警告を出すことができません でした。

ということで、いきなりですが、Disposeパターンを実装したクラスを継承する場合の正しいコードを掲載します。
もちろん、DelivedTypeの中で、破棄すべきフィールドを保持していた場合の コードになります。


Disposeパターンを実装したクラスを継承する場合は、 publicな、Disposeメソッドは 継承元で定義済みですので、改めてここで記述する必要はありません。
上記のように、引数ありのDisposeメソッドをoverrideするだけです。
このメソッドの中で継承元の Dispose(disposing) メソッドを忘れずに呼ぶようにします。

■FxCopのルール
CA2215:Dispose メソッドから基本クラスの破棄を呼び出します

  

Posted by gushwell at 23:26Comments(0)TrackBack(0)

2009年11月29日

FxCopに学ぶ番外編(6) : IDisposable を正しく実装します

   このエントリーをはてなブックマークに追加 Clip to Evernote

メールマガジン「C#プログラミングレッスン」では、今、[FxCopに学ぶ編] を連載中です。
そこで取上げようとしたルールで、下書きまでしたのですが、結局メルマガには書かないことにしたルールがいくつかあります。
そのまま捨ててしまうのはもったいないので、ブログに掲載します。


■IDisposableの実装(2)■
前回の続き
まず、なぜ、以下のクラスは、sealedを付加して継承できないようにしないと いけないのでしょうか?
前回のクラスを再度示します。


たとえば、Sampleを継承した、DelivedSampleを考えてみます。
このクラスにも、Dispoaseしないといけないフィールドが存在したとしましょ う。そうなると、必然的に、IDisposableインターフェースを実装しないとい けません。


しかし、このコードは、派生元のDisposeメソッドを隠すことになってしまい ます。
これだと、派生元のTextReaderオブジェクトを破棄することができませ ん。
つまり、Sampleクラスは、継承に対応していないクラスということになり ます。sealedを付けることで、表面上はこの問題を解決することができます。

無理やりコンパイルを通したとしても、以下のようなコードを書くと、


ポリモーフィズムが働きませんので、派生クラスDelivedSampleのDisposeメソ ッドが呼ばれず、DelivedSampleが保持しているリソースを破棄することがで きなくなってしまいます。

では、継承にも対応したクラスをお見せしましょう。


このコードの肝は、
  1. 複数回、Disposeが呼ばれても問題が発生しない。
  2. Finalaizeメソッド(デストラクタ)を実装することで、DIsposeを呼び出さなかった 場合でも、ガベージコレクション時にクリーンアップ処理をしている。
  3. Dispose を呼び出した場合は、GC.SuppressFinalize を呼び出し、 ファイナライズメソッドの呼び出しを抑制している。
  4. (ファイナライズでやることは、すでにDisposeでやっているから不要ということ)
  5. 実際のクリーンアップ処理を受け持つ、virtualで引数ありのDisposeメソ ッドを用意している。これで継承に対応可能。
の4点です。
これは、Disposeパターンと呼ばれているものです。詳しくは、
http://msdn.microsoft.com/ja-jp/library/fs2xkftw.aspx
をご覧ください。

■FxCopのルール
CA1063: IDisposable を正しく実装します

  
Posted by gushwell at 23:47Comments(7)TrackBack(0)

2009年11月26日

FxCopに学ぶ番外編(5) : 破棄できるフィールドは破棄します

   このエントリーをはてなブックマークに追加 Clip to Evernote

メールマガジン「C#プログラミングレッスン」では、今、[FxCopに学ぶ編] を連載中です。
そこで取上げようとしたルールで、下書きまでしたのですが、結局メルマガには書かないことにしたルールがいくつかあります。
そのまま捨ててしまうのはもったいないので、ブログに掲載します。


■IDisposableの実装(1)■


このコードの問題点はなんでしょうか?

それは、Sampleクラスが IDisposableインターフェースを実装していないこと が問題です。


とIDisposableを指定する必要があります。なぜIDisposableを実装しないと いけないのでしょうか。
それは、reader フィールドのTextReaderクラスがIDisposableを実装している クラスだからです。
TextReaderが使い終わったら、Dispose()メソッドを呼び出しリソースを解放する必要がありますが、それをど こでもやっていません。
どこでTextReaderクラスのDispose()を呼び出せばよいのでしょうか。Execや、Exec2メソッドの中でしょうか。 そうではありませんよね。
利用者側が、Execを呼び出さなかったら、Disposeはされないままですからね。
こんな時には、Sampleクラスにも、Disposeメソッドを定義し、Sampleクラス を利用する側から、Disposeを呼び出してもらえばいいのです。
それが以下のコードです。


使う側が、


とすれば、usingブロックを抜ける時に、Sample.Dispose()が呼ばれ、その中 で、TextReader.Disposeが呼ばれます。

これで、めでたしめでたし...
ではありません。実は、このコードはFxCopでは警告が出てしまいます。
この警告を手っ取り早く回避するには、


と sealed クラスにします。
しかし、sealedにするということは、このクラスから継承させることができな いということです。では継承を許し、かつ、IDisposableを実装するにはどう したら良いのでしょうか?

それは次回に解説します。


■FxCopのルール
CA2213: 破棄できるフィールドは破棄します

  
Posted by gushwell at 23:37Comments(0)TrackBack(0)

2007年07月10日

StreamWriter

   このエントリーをはてなブックマークに追加 Clip to Evernote
.NET Framework の System.IO.StreamWriterって、Disposeメソッドを持っているにも関わらず、IDisposableインターフェースじゃないんですよね。

何でだろう?
単なるバグでしょうか?

追記(訂正)7/12
StreamWriterは、ちゃんと IDisposableインターフェースでした。m(_ _)m
いったい、何を勘違いしていたんでしょうか?

さらに追記 7/12 21:42
StreamWriterを使ったソースを見てみると、

internal sealed class MySample : IMySample, IDisposable {
private StreamWriter _writer;

public FileStatusManager() {
...
_writer = new StreamWriter(filename, true);
}

public void Dispose() {
_writer.Dispose();
}
}


※ sealed なのd、DisposeはこれでOK.

って書いてあって、usingを使うようなコードじゃない。
他のソースで、Disposeメソッドを使っているところを検索してみたけど、
みんな、上記のような使いばかりで、
  Xxxx xx = new Xxxx();
...
xx.Dispose();


のように書いている箇所はなかった。

なんで、あんな勘違いをしたのか、良く思いだせない...

  
Posted by gushwell at 21:57Comments(2)TrackBack(0)