2014年7月1日火曜日

C#応用 – LINQプログラミング 8



さて、C#応用 LINQプログラミング

第8回である。


今回は、型とプロパティの説明である。



型・プロパティとLINQ
式の中で実行させたい処理を記述する際に必要である。

var query = ary.Where(x => myInclude(x)).Select( x => new { StationName = x } )

foreach(var item in query)
{
    Console.WriteLine(item.StationName);
}

var query の部分では型推論(後述)を行っている。

new { StationName = x } は初期化子で匿名型(後述)である。


自動実装プロパティ
    private string = _prop1;
    public string Prop1
    {
        get { return _prop1; }
        set { _prop1 = value; }
    }

上記と同様のことが下記で実現する。

    public string Prop1 { get; set; }

また、set のみ private にすることも可能である。

    public string Prop1 { get; private set; }


型推論
LINQを実現するにあたり、Saftyな型システムを維持しつつ可読性やコーディングへの

負担を減少させるための仕組みが必要となった。 ちなみに、読み方は 「バル」らしい。

    var a = 2;       // aはint
    var b = "abc";         // bはstring
    var c = (int) 1;         // cはint
    var d = new Hoge();  // dはHogeクラスのインスタンス

使用時の注意点
セットされる値からコンパイラが自動的に型を推論するため、変数への初期化が必須である。

数値や文字はリテラルもしくは書式により判定される。

var キーワードはローカルスコープのみ利用できる。


オブジェクト初期化子
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }

    var p new Person() { Name = "舞黒 太郎", Age = 20 };

公開されているフィールド・プロパティにコンストラクタを呼び出すことなく

値を割り当てることができる。

ただし、Null許容型(Nullable)には利用できない。


コレクション初期化子
    var plist = new List<Person>
        {
            new Person() { Name = "舞黒 太郎", Age = 30 },
            new Person() { Name = "大手 花子", Age = 25 }
        };

IEnumerableを実装するコレクションクラスを初期化する際に、

1つ以上の要素を初期化子として指定できる。

Addメソッドを複数回呼び出さなくともコンパイラによって呼び出しが追加される。


匿名型(Anonymous Type)
型推論、オブジェクト初期化子を利用し、型(クラス)を定義しないままの

オブジェクトを生成できる。

    var p = new { Name = "舞黒 太郎", Age = 30 };

    Console.WriteLine( "{0} 年齢は {1}", p.Name, p.Age);

これらは暗黙的に以下のことを行っている。
 ▻ 読み出しのみのプロパティとreadonlyのprivateフィールドを持つクラスの
  インスタンスを生成(つまり値は初期値から不変となる)

 ▻ 各プロパティ・フィールドの型はオブジェクト初期化子で初期化される値から推論される。

 ▻ クラスの定義そのものは公開されないため、匿名となる

 ▻ プロパティの並び順は厳格に保存される

上記のことから、var キーワードの利用が必須である。


匿名型の内部表現
以下の表現は
    var p = new { Name = "舞黒 太郎", Age = 30 };

コンパイラでは近似となる以下のコードに置き換わる。

  internal sealed class 匿名クラス<TName, TAge> {
        private readonly TName    __name;
        private readonly TAge       __age;

        public TName Name         { get { return __name; } }
        public TAge Age              { get { return __age;    } }
    }

    var p = new 匿名クラス<string, int> { Name = "舞黒 太郎", Age = 30 };


ラムダ式(2)
ラムダ式とは式とステートメントを含めることができる匿名関数であり、
デリゲート型または式ツリー型を作成するために使用できる。

・デリゲート
    delegate int dd(int i)
    dd myFunc = x => x * x;    // xがint型であることがコンパイラにより推論されている
    int v = myFunc(5);

・式ツリー
    Expression<dd> = x => x * x;


今日の名言
賽が投げられた自分の運命に自分自身を適応させよ。運命の女神が、
ともに生きるように定めた仲間を愛せよ。
                               マルクス・アウレリウス

ほとんどたいていの物事は、何の疑いもなく朗らかに受け入れれば、
様相を新たにする。
                               ヘンリー・S・ハスキンズ

この世であなたの主な目標は幸福である。幸福は健康とか名声には
左右されない。もっとも健康は幸福に大いに関係があるが、しかし幸福に
なれるかどうかを大きく左右するものがたった一つある。それは物の考え方だ!
自分の欲しいものが手に入らなければ、自分が今持っているものに対して
感謝することだ。些細なものが手に入らないからと愚痴を言わないで、
自分には感謝すべき大きなものがあることを常に考えるべきだ。
                               デール・カーネギー

真に人間らしい結びつきを得るには、人類が昔からやってきた通りにすれば
よい。神から与えられた我々の境遇、幸運の星のもと、我が祖国に
生まれた幸せを、スポーツマンのような態度で快く受け入れることだ。
                               ギルバート・キース・チェスタートン