2012年11月7日水曜日

[書籍]プログラミングC# を読んで

プログラミングC# を購入したので、読んで気づいた点などについて、書いていこうかなぁと思ってます。随時更新予定。


めんどくさいので3章から読み始めました。
3章 クラスと構造体によるアイデアの抽象化
・パスカル記法...GetString
型(クラスも型)/プロパティ/メソッドに使う
キャメル記法...bigCat
変数/フィールドとかに使う
・MSDNには命名規則を含むいろいろなガイドラインがある。
http://msdn.microsoft.com/ja-jp/library/ms229042(v=vs.100).aspx
・DRY・・・Don't Repeat yourself(自分で繰り返すな。)
・プロパティ : get/setを持つメンバ変数みたいなもの。
・フィールド : いつものメンバ変数。
・自動実装プロパティとは?
いままでこんな感じで書かなければいけなかったコード(C#3より前)
        private string myName;
        public string MyName
        {
            get
            {
                return myName;
            }
            set
            {
                myName = value;
            }
        }
を、こんな感じで省略できるようになったこと。
        public string MyName
        {
            get;
            set;
        }
C#コンパイラは、内部的には前者のようなコードを作ってるので、実装者からは見えないけど、プロパティに対応するフィールドが内部的には存在しているとのこと。

・読み取り専用フィールドとは?
最初に一回だけ(コンストラクタでだけ)書き込みが可能なフィールドのこと。
例えば猫クラスの名前のように、一度変更したら変えないようなフィールドに使用する。開発中に誤って名前を書き換えたりできないようにする意味があるとのこと。
    class Program
    {
        static void Main(string[] args)
        {
            cat tama = new cat("タマ");
            tama.SayName();
            Console.ReadKey();
        }
    }

    class cat
    {
        //読み取り専用フィールド
        private readonly string name;

        public cat(string newName)
        {
            name = newName;
        }

        public void SayName()
        {
            //name = "にゃんこ";  // ここを有効にするとコンパイルエラーになる。
            Console.WriteLine(name + "です。");
        }
    }
・クラスは値でなく参照型なので、代入しても実態は一つ。コピーされない。
            cat tama = new cat("タマ");
            tama.Age = 3;
            cat tama2 = tama;  // コピーはされない。tama2もtamaも同一。
            tama2.Age = 4;
とすると、tamaもtama2も4歳になる。
・参照型はヒープメモリに記録される。値型はいつもスタックに記録されるわけではない?(訳者が悪いのかどっちともとれるような書き方に...)
例えばクラスが持っているフィールドはヒープに作られる。

・構造体で既定のコンストラクタを提供しないでくださいとは?
MSDNの構造体のデザインでそういうことが書いてあるけど、どういう意味?と思ってました。その答えがとても丁寧に解説してあり、ようはデフォルトコンストラクタを独自に実装できないという理由とのこと。本にはもっと詳しく書いてある。
・フィールドだけの構造体の場合は、上記の内容に従ってデフォルトコンストラクタを書かなければ問題なしでこんな風に書ける。
        struct position
        {
            public position(int x, int y, int z)
            {
                m_x = x;
                m_y = y;
                m_z = z;
            }
            public int m_x;
            public int m_y;
            public int m_z;
        }
・なんだけどプロパティをもつ構造体の場合は、また制約があり、こういう風に書くとコンパイルエラーが発生する。デフォルトコンストラクタを呼ぶ前にメソッドを呼び出すとだめという制約がある。
        struct position
        {
            public position(int x, int y, int z)
            {
                X = x;
                Y = y;
                Z = z;
            }
            public int X { get; set; }
            public int Y { get; set; }
            public int Z { get; set; }
        }
で、これに対応する場合はこうすればい。
        struct position
        {
            public position(int x, int y, int z)
                :this()  // デフォルトコンストラクタを呼ぶ。
            {
                X = x;
                Y = y;
                Z = z;
            }
            public int X { get; set; }
            public int Y { get; set; }
            public int Z { get; set; }
        }
・C#4からは省略可能な引数というのがある。引数の数だけことなるようなオーバーロードをするときの代替として使える。型がちがうオーバーロードの代わりにはならないので、オーバーロードがいらなくなるわけではないと思う。 ・オブジェクト初期化子とは? newするときにプロパティを設定できる機能。コンストラクタとの使い分けが難しそう。。。
4章 拡張性とポリモーフィズム
・アソシエーションとは?
車と運転手
・集約(アグリゲート)とは?
消防車と着脱可能なホース(has-a)
・コンポジションとは?
はしご車とはしご(contains-a)
・継承とは?
消防署長と消防士(is-a)
・ポリモーフィズムとは?
消防署長クラスを消防署長と消防士の両方で使えるということ?こんなだったけ?
・リスコフの置換原則とは?
派生クラスは基底クラスに置き換えて使用できなきゃいけないよということ。
メソッドをオーバーライドしたらもうだめなのかな?
・継承するときのメソッドの修飾子newとoverrideは何が違うの?
別途まとめる。
・protectedってなに?
基底クラスのメンバなどにつける修飾子で、これをつけると派生クラスからだけは使えるようになる。publicとprivateのあいだぐらいのもの。
・internalってなに?
これをつけると別のライブラリから使えなくなる。あまり使用されてないみたいだけど、使ったほうがよいのだとか。
・sealedってなに?
これをつけると、派生できなくなる。派生させたくないクラスにはこれをつけとくとよい。
・抽象クラスのなまえは~baseにしたほうがよい。
・すべての型はObjectの派生である。(intとかもすべてのclassもobjectの派生)
・ボックス化ってなに?
objectがたの変数に値を代入すること。(とても重い)
・ボックス化の解除ってなに?
object型の変数を別の型の変数に代入すること。(こちらも重いがボックス化よりは軽い)
・C#では多重継承がないかわりにインタフェースがある。
・インタフェースって何?
イメージとしては抽象クラスのような感じ。使い分けはよくわからないけど、インタフェースの方が使いやすいのかな?
インタフェースは多重継承みたいなことができる。

5章 デリゲートによる関数合成
・デリゲートとは「単に、任意の関数をいくつかのプロパティに登録し、順番に呼び出すオブジェクトでしかない」とのこと。
・5-1まで読んだが、なんだがしっくりこず。http://ufcpp.net/study/csharp/sp_delegate.html こちらのほうが参考になった。関数を型として扱うような感じとのこと。deleget ~と宣言するとそれと同じ引数と戻り値をもった関数を同じ型として扱うことができる。(別途まとめたい) ・戻り値を持たないデリゲートの場合は、型を宣言しなjくてもAction<引数>というもので代用できる。
・デリゲート型の変数をプロパティとすることもできる。その場合、関数をgetしたり、setしたりできる。
・匿名メソッドは親の関数で定義されている変数にもアクセスできる。
・その他は別の記事にまとめた。
6章 エラー処理
・エラーが起きたときの対処策としては、一般的には次の方法がある。
1.気にせず継続する
2.対処する(まるめるとかそんな感じ。)
3.エラー値で処理する
4.停止する。

で、1だと期待した結果にならなかったり、プログラムが突然落ちたりなんかするのでNG
2だといい場合もあるけど、ダメな場合もある。
※詳細は書籍で。
3だと正常系と同じぐらい異常系のためのコードが必要になり、それ以外にもいろいろ大変とのこと。
4については説明がないけど、なので、例外を使いましょうという感じ。
・例外(excepttion)を使うメリットは?
 エラー処理が不要になる。(エラーコードを伝搬させるよくある処理)
 (⇒サブサブサブサブ関数で、エラーが起きたときに例外を投げれば、一番上まで届くので)
 ということで、エラー系にひとまず頭をなやませなくてもよい。
 デバッカを使っていれば、エラーが発生した場所(exception)した場所が明確にわかる。
・暗黙的な再スローって何?
throw;でもう一回スローすること。
この方法だと呼び出し履歴の情報がのこるとのこと。
・明示的な再スローってなに?
throw 例外オブジェクト;でスローしなおすこと
この方法だと呼び出し履歴の情報が再スローしなおしたところからになるとのこと。
再スローしなおすと、元の例外は再スローした例外のinnerExceptionプロパティとして記録される。
・カスタムの例外はできるだけ使わないほうがよい。

7章 配列とリスト
・配列にはFindAllというメソッドがある。便利そう。
・多次元配列には、配列の配列 int[][]と
・四角形配列 int[ , ]がある。
0 件のコメント:
コメントを投稿