2010年05月23日

FxCopに学ぶ番外編 目次

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

1. シールされた型にプロテクト メンバを宣言しないでください

2. 標準の例外コンストラクタを実装します

3. シリアル化コンストラクタを実装します

4. ISerializable を正しく実装します

5. 破棄できるフィールドは破棄します

6. IDisposable を正しく実装します

7. Dispose メソッドから基本クラスの破棄を呼び出します

メールマガジン「C#プログラミングレッスン」[FxCopに学ぶ編] (No219 - No235)では、
FxCopのルールから解かるC#の正しいコードの書き方についての記事を書きましたが、
そこに取り上げなかったルールをいくつか解説しています。
この番外編は、内容的には中級者以上の方向けの内容になっていると思います。
多くの記事の中に埋もれてしまうのは惜しいので、目次をアップします。
  

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

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)

2009年11月23日

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

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

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

■独自例外クラスの書き方(3)■■

MyExceptionに独自のプロパティを追加したとします。


このコードを FxCopに食わせると、GetObjectDataの実装を型 MyException に追加してくださいという警告が出ます。

これは、独自のプロパティを正しくシリアライズするために GetObjectDataメソッドを overrideする必要があることを示しています。
独自のフィールド/プロパティを持つ例外クラスを作成する場合は、GetObjectDataをoverrideする必要があります。

GetObjectDataメソッドを実装した MyExceptionを示します。


MyException(SerializationInfo info, StreamingContext context) コンストラクタも変更されていいる点に注意してください。
これで、シリアライズ、デシリアライズに対応させることができます。

■FxCopのルール
CA2240: ISerializable を正しく実装します

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

2009年11月19日

FxCopに学ぶ番外編(3) : シリアル化コンストラクタを実装します

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

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


前回の続きです。

■■独自例外クラスの書き方(2)■■

前回は、


と書きましたが、まだ、コンストラクタが不足しています。


というコンストラクタを定義する必要があります。
これがないと、この例外をシリアル化することができません。
例えば、ネットワーク越しにこの例外を伝えたいような場合、このコンストラクタが無いと正しく動作しません。

それには、以下のように修正する必要があります。


■FxCopのルール
CA2229: シリアル化コンストラクタを実装します

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

2009年11月17日

FxCopに学ぶ番外編(2) : 標準の例外コンストラクタを実装します

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

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


今回は、例外クラスの書き方のルール

■■独自例外クラスの書き方(1)■■

の問題点はなんでしょうか。

まずは、ある例外が発生した際に、その例外を このMyExceptionにラップしようとしても、それが出来ない点が問題です。


というコードが書けません。


だと、System.ArgumentNullException が発生したという情報を innnerExceptionに設定することができません。


というコンストラクタを定義してやる必要があります。
しかし、これだけではまだ不十分です。それはまた次回に。

■FxCopのルール
CA1032: 標準の例外コンストラクタを実装します

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

2009年11月15日

FxCopに学ぶ番外編(1) : シールされた型にプロテクト メンバを宣言しないでください

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

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


次のコードのおかしな点は?
protected にするということは、派生クラスで利用できるということですが、シールされているので、ここから派生させることはできません。
つまり、sealed と protectedは相矛盾する指定ですので、シールされた型にプ ロテクト メンバを宣言してはいけません。

これって、コンパイルエラーにしても良いのにね。

■FxCopのルール
CA1047: シールされた型にプロテクト メンバを宣言しないでください
  
Posted by gushwell at 22:31Comments(0)TrackBack(0)