try-catchを吐き出すスニペットが[try]であることに対して、
try-finallyを吐き出すスニペットは[tryf]である。
これが、
try-catchを吐き出すスニペットが[tryc]であることに対して、
try-finallyを吐き出すスニペットは[try]である。
だったら、もう少し無駄なcatchが減るのかもしれないなぁ。
最初に断っておきたいこと
VB9の話です。 匿名型自体の説明はしていません。 最後になぜ今回はC#ではなくVBなのか説明します。 簡単なサンプルにするため仕様がシンプルで効果を感じられないかもしれませんが、 もしもっと複雑な仕様だったら等、想像してみてください。
まず最初に先日の匿名メソッドのエントリでも私が考える読みやすいコードの要素について書きましたが、今回は
1.処理のスコープを最小にする。
2.よりコードに意味を持たせる。
という2点について注目していきたいと思います。
まず最初に、下記のサンプルを見てください。
簡単な仕様として、引数で渡された在庫リストの数量と金額の合計を算出します。
Public Class 在庫 Public 数量 As Integer Public 金額 As Integer ''以下定義が続く End Class Public Class サンプル1 Public Sub サンプルメソッド(ByVal 在庫リスト As 在庫()) Dim 数量計 As Integer = 0 Dim 金額計 As Integer = 0 For Each 在庫情報 As 在庫 In 在庫リスト 数量計 = 在庫情報.数量 金額計 = 在庫情報.金額 Next End Sub End Class
この例の場合、確かに、数量計と金額計を算出したいのはわかりますが、数量計と金額計はそれぞれ独立した変数となっているため、関連があることをコード上に残せていません。
そこで次のサンプルを見てください。
Public Class サンプル2 Private Class 在庫計 Public 数量計 As Integer = 0 Public 金額計 As Integer = 0 End Class Public Sub サンプルメソッド(ByVal 在庫リスト As 在庫()) Dim 在庫計情報 As New 在庫計 For Each 在庫情報 As 在庫 In 在庫リスト 在庫計情報.数量計 = 在庫情報.数量 在庫計情報.金額計 = 在庫情報.金額 Next End Sub End Class
privateなinner classである在庫計を作成し、サンプルメソッド内で、インスタンスを生成し利用することで、数量計と金額計は独立した変数ではないという事と、在庫の合計を保持しているという意味を持たせる事ができました。
その反面、在庫計クラスはサンプル2クラス全体から利用できるようになってしまいましたので、ほかのメソッドでも使っているかもしれない可能性が生まれてしまいました。
ここで、次のサンプルを見てください。
Public Class サンプル3 Public Sub サンプルメソッド(ByVal 在庫リスト As 在庫()) Dim 在庫計情報 = New With {.数量計 = 0, .金額計 = 0} For Each 在庫情報 As 在庫 In 在庫リスト 在庫計情報.数量計 = 在庫情報.数量 在庫計情報.金額計 = 在庫情報.金額 Next End Sub End Class
数量計と金額計をメンバに持った匿名型としてインスタンスを生成し、変数に適切な名前を設定することで、サンプル2の利点を生かしたまま、在庫計というクラスを作成しているわけではないので、他のメソッドでも利用されているかもしれないといった可能性が発生しなくなりました。
このように、匿名型を利用することで、できるだけ少ない範囲のスコープを維持したまま、よりコードに意味を持たせる事ができます。
最後に、何故C#ではなくVBで書いたのかというと、
C#の匿名型はメンバがすべて読み取り専用のプロパティとして宣言されるため、最初に宣言した時に設定した値を変更する事ができないからです。
VBでいうところの
Public Class サンプル4 Public Sub サンプルメソッド(ByVal 在庫リスト As 在庫()) Dim 在庫計情報 = New With {key .数量計 = 0,key .金額計 = 0} For Each 在庫情報 As 在庫 In 在庫リスト 在庫計情報.数量計 = 在庫情報.数量 在庫計情報.金額計 = 在庫情報.金額 Next End Sub End Class
というコードになってしまい、コンパイルエラーになるという事ですね。
では、最初の設定時に集計した値を設定してやれば良いのですが、その話は次回以降のエントリにします。
最初に断っておきたいこと
C#3.0の話です。 Func型や匿名メソッド自体の説明はしていません。
まず最初に、私が考える読みやすいコードの要素について断片的に提示します。
1.処理のスコープを最小にする。
2.今、読みたい粒度のコードしか読まなくても良い。
というものがあります。
どれも、いくつかある読みやすいコードの要素の断片でしかありませんが、この1と2は矛盾を孕んでいます。
それでは、どんな矛盾を孕んでいるかサンプルを交えて説明します。
001 public class サンプル1 002 { 003 public void サンプルメソッド() 004 { 005 if (鼻毛抜きの在庫 == 0 && 鼻毛カッターの在庫 == 0) 006 { 007 return; 008 } 009 010 鼻毛処理(); 011 } 012 } 013
鼻毛処理のできる道具があれば、鼻毛処理ができる。
という仕様を実現しています。
しかしながら、「鼻毛処理のできる道具があれば」の詳細部分まで同じメソッド内に記述されてしまっています。
そこで、
001 public class サンプル2 002 { 003 public void サンプルメソッド() 004 { 005 if (!鼻毛処理の道具がある()) 006 { 007 return; 008 } 009 010 鼻毛処理(); 011 } 012 013 private bool 鼻毛処理の道具がある() 014 { 015 if (鼻毛抜きの在庫 > 0) 016 { 017 return true; 018 } 019 020 if (鼻毛カッターの在庫 > 0) 021 { 022 return true; 023 } 024 025 return false; 026 } 027 028 public void その他の処理() 029 { 030 throw new NotImplementedException(); 031 } 032 033 } 034
これで、「2.今、読みたい粒度のコードしか読まなくても良い。」という要素が満たされた実装になりました。
しかしメソッドアウトする前は、処理のスコープがメソッド内にしかなかったのに、メソッドアウトした事で処理のスコープがクラス全体に広がってしまいました。
実装したばかりの今なら、まだサンプルメソッド内でしか使われていないとわかりますが、将来このコードを見たときに、サンプルメソッド内でしか使われていないと断定することができません。
これでは、「1.処理のスコープを最小にする」という要素が満たされなくなってしまっています。
そこで、以下のようにFunc型と匿名メソッドを利用してサンプルを修正してみます。
001 public class サンプル3 002 { 003 public void サンプルメソッド() 004 { 005 Func<bool> 鼻毛処理の道具がある = 006 delegate 007 { 008 if (鼻毛抜きの在庫 > 0) 009 { 010 return true; 011 } 012 013 if (鼻毛カッターの在庫 > 0) 014 { 015 return true; 016 } 017 018 return false; 019 }; 020 021 if (!鼻毛処理の道具がある()) 022 { 023 return ; 024 } 025 026 鼻毛処理(); 027 } 028
これで、匿名メソッドという形でメソッドアウトし「2.今、読みたい粒度のコードしか読まなくても良い。」という要素を満たした上に、処理のスコープもメソッド内にとどまりますので、「1.処理のスコープを最小にする。」という要素も満たされます。
「鼻毛処理の道具があれば」という仕様の詳細まで知る必要が無いときは匿名メソッドを読み飛ばせば良いのです。
以上のように「ひとつのメソッドの中でしか利用しないが、粒度が違うためメソッドアウトする。」といったような局面において最小のスコープを維持したままメソッドアウトする道具として匿名メソッドを使う例の紹介でした。
ちなみに、サンプル3をラムダ式で書くと
001 public class サンプル3 002 { 003 public void サンプルメソッド() 004 { 005 Func<bool> 鼻毛処理の道具がある = 006 () => 007 { 008 if (鼻毛抜きの在庫 > 0) 009 { 010 return true; 011 } 012 013 if (鼻毛カッターの在庫 > 0) 014 { 015 return true; 016 } 017 018 return false; 019 }; 020 021 if (!鼻毛処理の道具がある()) 022 { 023 return ; 024 } 025 026 鼻毛処理(); 027 } 028
となります。
Zipファイルの解凍をするのに、
.NET Framework3.0で提供されている
System.IO.Packaging名前空間のZipPackageを利用しようとしたのだが、
package相当のZipファイル以外は、パブリックではないメンバであるZipArchiveに中の情報が入っているにも関わらず、Partとしては取得できない・・・。
ZipArchiveのクラスはMS.Internal.IO.ZIP名前空間で、どうも普通には利用できない。
できるだけリフレクションを使わないでいけたらよかったのだけど、リフレクション使わないといけないっぽい。
codeplexにサンプルがあったので、ちょっと見てみようかな。
こちらのblogからです。
Robert McLaws: Windows Vista Edition : .NET Framework 3.0 WinFX RTM
VistaのRTMよりも一足先に.NET Framework 3.0がRTMしたようです。
こちらからダウンロードすることができます。
もうちょっと先だと思っていました。
欲しかった。
すべてはここから始まった??SHA-1の脆弱化 ?? @IT
MD5/SHA-1は新規システムの開発では採用するべきではありません。
これらには既知の脆弱性が存在し、短時間でハッシュ値を重複させる攻撃が可能となっております。
同感です。
菊池さんのブログにあるように、Obsolete属性がついていれば、
何も考えなくても使わない人が増えそうですね。
ちなみに、うちは、SHA512を使うことが多いです。
そんなにコストのかかる処理ではないので・・・。
http://www.microsoft.com/japan/msdn/vstudio/
Visual Studio ホームページ
最新情報
Team Foundation Server 導入に関するホワイトペーパー
Team Foundation Server 導入において計画段階での検討点、インストールと管理に関する検討点、構成と管理に関する検討点に関して必要な情報に対するインデックスを Quick Start %2
備忘録としてメモ
このペーパーでは、.NET Framework に組み込まれているライセンス処理方式についての詳しい情報を提供します。また、利用可能な各種のライセンス処理方式と、一部の方式を .NET Framework で実装する方法について説明します。.NET のコントロールとコンポーネントのプロとしてやっていくためには、これらの事柄を理解する必要があります。
そのうち使いそうなので、ずいぶん前にメモっておいたURLをここに貼り付け。