« 有須子がtwitterに出現 | メイン | iPhoneアプリ不要 iPhone/iPod touchからブラウザ経由でマウスをエミュレートする「Ajax Mouse」 »

C#の絵本を読んで

「C#の絵本」を読んでの個人的メモ兼簡単な書評。
挿絵も工夫されていて、読みやすい本だった。プログラム初心者にも安心して勧められると思う。他の絵本シリーズも読んでみたくなった。ただ、サンプルコードの品質が気になった。プログラム的には問題ない場合が多いけど、文言が問題だと思う。詳細は後述のメモと実際に本を手に取って確かめて欲しい。
以下、思った事を列挙。メモ内の例は基本的に書籍とは異なっている。
[xi]
覚えておきたい用語 「JIT(Just In Time)コンパイラ」。「Just In Time」は「逐一」という意味。
[xi]
覚えておきたい用語 「中間言語(IL:Intermediate Language)」。
[P2]
覚えておきたい用語 「エントリポイント」。プログラムの実行開始点の事。
[P16]
2次元以上の配列で、同一次元の要素数が異なる配列をジャグ配列というらしい。
[P17]
ジャグ配列の例
    int[,] ary = new int[3,4];                                  //ジャグ配列ではない(呼称不明)
    int[][] ary = new int[][]{new int[]{1,2},new int[]{3,4,5}}; //ジャグ配列
[P19]
列挙型の例
    enum Sample{apple,box,cat=10,desk};
    Sample s;
    s=Sample.apple;
    Console.WriteLine(Sample.box);      //=>box
    Console.WriteLine((int)Sample.cat); //=>10
[P33]
「&&」「||」は不要な評価はしない。短縮評価と言うらしい。「&」「|」は全て評価される。ビット演算子以外にも使えるようだ。
[P38]
checked文を使うとオーバーフローを起こした時に例外を発生させる事ができる。逆にunchecked文はオーバーフローを無視する。通常はuncheckedの状態。
[P70~P71]
ブロックの内外で同じ名前の変数は宣言できない。但し、クラスのフィールド名とローカルの変数名は同じでも構わない。この時、ローカルからフィールドを参照するには「this.[フィールド名]」を使う。
[P77]
この実行例、ちょっと微妙。引数の文字数によって出力位置が変わるため、メソッド内にスペースを固定で埋め込んで表示位置を調整している。こんな事するぐらいなら引数の文字数を揃えた方が良い。
[P82]
コピーコンストラクタはcloneメソッドでは駄目なのだろうか。それともcloneメソッドがないのか?
[P84]
JavaScriptだと、フィールドとプロパティの違いは余り意識しなくても使えるため、用語も結構混同して使ってしまっている。本来は違う概念だし、C#では書き方も違う。
[P86]
インデクサというのは初めて聞いたかもしれない。プロパティと配列が合わさったようなものと理解した。
[P88]
Mainメソッドの戻り値は通常voidであるが、intに変更すると正常終了したかどうかを返す事ができる。0の時は正常終了。
[P89]
コマンドライン引数はMainメソッドが文字列配列として受け取る。
[P102]
継承させたくないクラスにはsealedをつける。Javaでいうfinalみたいなものか。
[P103]
この実行例も良くないと思う。買い物をするような例なのに、所持金がマイナスになっている。「if (money + In - Out < 0)」で判定後、elseの中で「money = money + In - Out;」とする方が良いと思う。
[P105]
親クラスのコンストラクタに引数がある時、子クラスのコンストラクタで親クラスのコンストラクタを指定するには「base」を使う。
    class Child : Parent{
        public Child(int i) : base(i){}
    }
[P106]
親クラスのメンバと同じ名前のメンバを子クラスで宣言したい時は、newをつけなければならない。別のキーワードはなかったのかな。オブジェクト生成と紛らわしい。
[P107]
親クラスはbaseで参照可能。newで親クラスのメンバを隠匿している時もbase経由で参照できる。
[P108]
オーバーライドが前提のメソッドにはvirtual修飾子を使う。仮想メソッドというらしい。抽象メソッドと何が違うのか不明。
[P108]
virtualで宣言された親クラスのメソッドはoverride修飾子をつけて上書きする。
[P111]
実行結果に「3文字分のスペースがあく」とあるが本当にあくのだろうか。char配列を初期化した後、0~2の要素には何もしていないので値はnullのはず。Console.Writeにnullを渡すと半角スペースを出力するような仕様になっているのだろうか。
[P114]
サンプルプログラムは微妙。
「定規」のクラスなら角度と長さは正負のバリデーションが欲しい。せめて「図形」クラスを例にしたほうが良かったのではないか。素材は色で代用できるはず。後、TriangleRulerのgetInfo内の日本語部分、「°」が「。」になっている。
[P116]
C#ではメソッドの呼び出しは基本的に値渡し。意図的に参照渡しにしたい時には、呼び出し元・呼び出し先共に「ref」が必要らしい。どちらかだけに「ref」がついていたらどんな動きをするんだろうか。クラスはそもそも参照型なので、必然的に参照渡しになるとある。多分これは、アドレスへの参照を値渡しするためこのようになっているはず。「ref」に似た「out」というものもあるが、こちらは引数として渡す前の代入が不要らしい。
[P119]
多態性(ポリモーフィズム)の概念を10年ぐらい勘違いして覚えていた。「あるクラスの性質が継承によって他のクラスに広がっていく事」だと思っていた。正しくは、「あるクラスが継承によって他のクラスの様にも振る舞える事」を指すらしい。逆にこの性質に名前があったんだという印象で、継承の利点のひとつとしか捉えていなかった。
[P121]
抽象クラスの抽象メソッドの上書きにもoverrideが必要らしい。
[P122]
インターフェイスの抽象メソッドの上書きにはoverrideは不要らしい。
[P122]
インターフェイスを実装するためには「:」を使う。これはクラスを継承するときと同じ。Javaでは両者を文法上、区別するがC#では区別しない。
[P123]
インターフェイス定義の抽象メソッドは、インターフェイスの実装側で全てが必ずpublicで実装されなければならないため、publicは省略できる。
[P123]
インターフェイスを複数実装する時は「,」で区切る。クラスを継承しつつインターフェイスを複数実装するには、どう書くのだろうか。
[P125]
インターフェイスがインターフェイスを継承する際に、同名のメンバがある場合、継承先の抽象メンバを優先的に扱うために「new」をつける必要がある。
[P132~133]
オブジェクトクラスに値型のデータを代入する事をボックス化(boxing)、逆にボックス化されたデータを値型に戻す事をボックス化解除(unboxing)と言うらしい。int型をボックス化すると、内部ではInt32構造体の形で保存されるらしい。
    int i=1;
    Object o=i; //ボックス化
    int j=o; //ボックス化解除
[P134~135]
Javaでいうパッケージの概念はC#ではnamespaceを使って実現するようだ。Javaではpackageの宣言文だが、C#ではnamespaceブロックを使う。名前空間の階層はnamespaceブロックのネストで対応できる。階層が深い名前空間は、インデントが深くなり過ぎてコーディングがしにくそうという印象を受けた。宣言で対応できる等の別の仕組みがあるのかもしれない。(以前見たjavaScriptで名前空間を強引につくる方法を思い出した。)
[P136~137]
javaのimportと同じ事は、C#ではusingで宣言する。「using S = Sample;」のように別名をつける事も可能。
[P140]
is演算子は「is a」「has a」のisの事かも。「a is A」は「aはAの一種」という感じか。as演算子は型変換。「B b = a as B;」のように使う。キャストとの違いは型変換不能の時の動作で、キャストは例外となるがasはnullを返すところ。
[P147]
throw文の説明にあるコード内、catchで受けているExceptionの変数名とcatch内で宣言されているExceptionの変数名が同じになっている。コンパイルエラーになりそうだ。
[P156]
StreamWriter型の変数wのメソッドCloseのカッコが閉じられていない。
[P163]
桁数の指定の説明のはずなのに、実行例が微妙。数値の桁が指定された桁数よりも小さいため、サンプルがほとんど意味をなしていない。
[P164]
Emptyフィールドの用途がわからない。「string c = "";」と何が違うのだろうか。
[P171]
またまたサンプルが微妙。正規表現が"C.*の絵本"なのに結果の文言が「C#の記述があります」となっている。これだと「Cの絵本」でも「COBOLの絵本」でも一致するため、「C#の記述があります」と表示されてしまう。
[P175]
ここもサンプルが...。問題が3文字未満だった場合、ヒントのところがおかしくなる。問題を読み込む時に3文字以上でないと読み込まないようにするとか、3文字以上でないとヒントは出さないとか、せめて「問題は3文字以上になるようにして下さい。」と注意書きを入れるとか、何らかの手を打っておいて欲しかった。
[P176]
デストラクタの定義方法は「~(チルダ)」をつけたクラス名と同じメソッド。Javaではfinalizeなんだけど、ここではC++の文法が採用されている。Javaではfinalizeが実行される前にJavaVMが終了する事もあるらしいけど、C#ではどうなのだろうか。
[P178]
ジェネリッククラスはダッグタイピングのような事をするための仕組みと理解した。
[P180]
デリゲートを使うと、メソッドを高階関数のようにできるようだ。
[P180]
「DelegateClass dc = new DelegateClass(method);」は「DelegateClass dc = method;」とも書けるらしい。
[P181]
デリゲートのマルチキャストについて書かれているが、どう便利なのかが理解できない。メソッドをふたつ追加したデリゲートに引数を渡して実行するとどうなるのか、最初に実行されるメソッドの戻り値はどうなるのか等、もう少し詳細な説明が欲しいところ。
[P183]
イベントでのデリゲートの使い方を見ていると、JavaScriptのaddEventListenerとremoveEventListenerに近い使い方をしている。プロパティの宣言と似ているadd/removeを使ったeventの宣言例は、正にそんな印象を受ける。そもそも、デリゲートのマルチキャストは、イベントを想定してのものなのかもしれない。
[P185]
ひとつ目のWriteLineの第一引数の引用符が閉じていない。
[P186]
プリミティブ型は通常nullを許さないが、null許容型(Nullable Type)で宣言する事でnullを代入できるようになるらしい。書き方は「int? i = null;」で、これは「System.Nullable<int> i = null;」のsyntax sugerとの事。つまり、null許容型はジェネリッククラスで実現されているということらしい。
[P187]
null許容型はふたつのプロパティを持つ。nullの時にfalseを返す「HasValue」と、値を返すがnullの時は例外となる「Value」。
[P187]
値型の値をnull許容型の変数に代入する時は暗黙の型変換が行われる。逆にnull許容型の値を値型の変数に代入する時は明示的にキャストしなければならないらしい。ただし「??」を使いnullであった時の値を定義しておけば、キャストは不要になる。「int? i = null;int j = i ?? 0;」
[P202]
Visual C#で生成したプログラムは次のようなディレクトリ構成になるらしい。
    ドキュメント
     ┗Visual Studio 2008
      ┗Projects
       ┗[ソリューション名]
        ┗[プロジェクト名]
         ┣[ソースファイル]
         ┗bin
          ┣Debug
          ┃┗[Debugモード実行ファイル]
          ┗Release
           ┗[Releaseモード実行ファイル]
[P203]
環境変数Pathに「%SystemRoot%\Microsoft.NET\Framework\v3.5」と登録しておくと、コマンドプロンプトから「csc [ソースファイル名]」でコンパイルできるようになるらしい。

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

Google

タグ クラウド