ページ

2010年3月21日日曜日

C#勉強中 C# 3.0入門 2-5

間が空きましたが C# 3.0入門の続きをば
  • 第2回 ラムダ式と型推論
    最初の節はラムダ式そのものよりも、Attribute(Reflection)の効率的な使用法だと思えます。ここではラムダ式、delegateを使うことにより、Reflectionの参照を最小限に抑えている点の方が役に立っています。まあ、ラムダ式の使い方の一種ではあるのでしょうね。
    次の節の前半はシステム規定のdelegateの型。ActionとPredicateは良く使いそうです(というか、このレベルのdelegateを自前で定義しないよいうに注意しないといけませんね)。Funcシリーズはちょっと微妙。頭に記載されているように、汎用過ぎて正当性のチェックとかが無意味になってしまう可能性が出てきます。このレベルになると自前で宣言した方が可視性が上がるように思えますね。後半はラムダ式での型推論の話。確かに型推論で記述量が減るのは認めますが、こういうシステムの入り組んだ処理に頼って記述を減らすのはどうかと思いますね。良く言われる例ですが、演算子の優先順位に頼らず、無駄に括弧を付けた方が良い、というのを思い出します。まあ、単純/明快な推論でカバーできるならともかく、ここの最後の例なんかはあまり嬉しく無いでしょう。ちなみに個人的にはエレガントとというよりは悪趣味の世界に入り込んでいると思いますね。
    前節の後ろから次節の前半で、やっと本質的なdelegateとlambdaの違いが出てきました。本質的にはdelegateは匿名(無名)関数、lambdaは式ツリー(Expression Tree)なのですね。ただ、式ツリーをdelegateの式(関数)としても使用可能だということのようです。式ツリーはコンパイル時に生成されるものなので、コードの中で動的に変更可能な式を作成する手段が提供されることになります。通常のコードではこのような機能が使いません。しかし次回予告にあるようにLINQがこれを使って実現されているようで、たしかに検索の条件を実行コードに落とすようなケースでは必要になりそうです。
  • 第3回 varによる変数宣言とコレクション初期化子
    ちなみに私、個人的には「過剰な否定」派であること明記しておきます。LLでなんども意図しない型変換で泣いておりますので。でまずは、コンパイル時に型が確定するのでひと安心です。これも型推論に基づく省略記法に過ぎないのでしょうか?たしかにオブジェクトをnewして変数に格納するときの冗長性は腹がたちますので、これが簡略化されるのは悪いことではありません(このケースでは型推論と言っても明確そのものです)。ただ型推論が難しくなるようなケース(次節の配列問題とか)ではやはり避けたいところです。
    最後の節はコレクション初期化子の話題で、C#ではコレクションに対する初期化子の記述が可能になったというものです。前に触った時だと、perlでは不可、pythonでは可能だったように記憶しています。でコレクションの初期化を使いたいばかりにpythonで書いたりしましたが。便利になった、と思ったら単なるシンタックスシュガーとのこと。ちょっとがっかりですが、ソースは見た目、ということでOKとしましょう。Dictionaryにも初期化設定が可能になっているのは有り難いですね。
  • 第4回 自動実装と自動定義
    自動実装プロパティって便利なのでしょうか?よく使うパターンでは、内部的には自由なアクセスを、外部からは特定のメソッドによるアクセスのみを提供しますが、内部からでもプロパティ経由でしかアクセスできないという点で引いてしまいます。確かに一部の(オブジェクト指向をどう誤解したんだよという)アクセッサ至上主義の人達には愛用されそうですが。単純なデータ保持のためのクラスと言ったものの場合には便利になるのかもしれません。そういえば、この手のデータ保持のためのクラスみたいなものも無いわけではありませんからね。
    と、次の節ではまさにデータを保持するためだけの匿名型が出てきました。初期化のみ可能な読み出し専用のプロパティを持ったクラスです。型チェック云々を気にしなければDictionaryででも実装できそうなデータオブジェクトです。ただ、C#では、初期化子の識別名と初期化値に基づく型が推定されるようで、コンパイル時に型チェックの対象となる点でしっかりした型(オブジェクト)になっています。で、何に使うかといえば、LINQのselectの結果を保持するため、といいきってもいいかと。同様に、データ項目が動的に変化するような処理結果を保持するデータ型として使えるでしょう(古い言語ではKey/Valueペアの集合で表現していたようなものです)。
    最後の節は、オブジェクト初期化子の話。匿名型はオブジェクト初期化子からの型推論によって自動的に(名無しの)型(オブジェクト)を生成していたわけで、初期化子自体は任意のオブジェクトの初期化に使えます。ここではオブジェクトの初期化の順序/制限について解説しています。宣言→コンストラクタ→初期化子という順番はまあ期待通りなので何も問題はありません。問題になるのは、初期化子ではprivate/readonlyフィールドへの設定ができないという点でしょう。確かに仕組みでいえば当然なのですが、あるクラスで固定的なデータを用意するような場合にはオブジェクト初期化子による生成ができない点は残念です。概念的にはオブジェクトの初期化と考えるよりも構造体の初期化に近いイメージで捉えた方が良さそうです。
  • 第5回 拡張メソッド
    普通にクラスで定義するメソッドでも、インスタンスメソッドとして定義したもの「obj.method()」と、自オブジェクトをパラメタとして渡すクラスメソッド「method(obj)」とを用意することがあります。内部データにアクセスしないのであればクラスメソッドは外部で定義しても構いません。拡張メソッドは、このような外部で定義された(オブジェクトインスタンスをパラメタとする)メソッドを、クラスメソッドと同じ形式で呼び出すことができるようにした、ある種のシンタックスシュガーのようです。まあ、既存クラスに対するある種の拡張システムと考えればいいのでしょう。
この後は.NET 3.5の花形、LINQの解説になりますので、今日のところはここまでにしておきます。

0 件のコメント:

コメントを投稿