C#3.0をさわってみる

Silverlightを勉強するつもりでVS2008 Beta2をダウンロードしたが、C#3.0が気になって仕方がないのでちょっとだけさわってみた。

型推論

まずは型推論C#2.0までは型を宣言する場合、必ず型を明示する必要があったが3.0からは型が文脈から推論できる場合のみ型宣言を省略できるようになる。(ただしローカル変数のみ)

var s = "Hello";    // string型
var i = 1;          // int型
var intArray = new int[] { 1, 2, 3 };    // int型の配列

オブジェクト初期化子

オブジェクトの初期化と同時に各プロパティに値を設定するためには、コンストラクタの引数で渡すしか方法がなかった。3.0からは初期化と同時に任意のプロパティに値を設定する事ができるようになる。

class Entity {
    private string name;
    private int number;
    public string Name {
        get { return name; }
        set { name = value; }
    }
    public int Number {
        get { return number; }
        set { number = value; }
    }
}

「Name」と「Number」というプロパティを持つクラスを定義して、それを初期化するコードを以下のように書く事ができる。

var o1 = new Entity { Name="Hoge", Number=1 };
var o2 = new Entity { Name="HogeHoge" };

これでプロパティ初期化用のコンストラクタを書く必要がなくなる。

リスト初期化子

配列やコレクションの初期化も簡単に行う事ができる。

var intArray = new[] { 1, 2, 3 };    // int型の配列
var strArray = new[] { 1, 2, 3 };    // string型の配列

var intList = new List<int> { 1, 2, 3 }:    // int型のジェネリックリスト

配列の各要素から型を推論してくれるわけだ。もちろん全ての要素の型が同じ必要がある。最後のはリスト初期化子かどうかはわからないけど便利。

匿名型

なんらかの処理を書くときに処理データの一時的な格納用として最小限のプロパティのみを備えたインナークラスを定義する事がよくあるが、3.0からはクラスをいちいち定義しなくてもこういった事ができるようになる。

先ほどのEntityクラスを匿名型で表現すると以下のようになる。

var o1 = new { Name="Hoge", Number=1 };
var o2 = new { Name="HogeHoge", Number=1 };

o2の初期化子では先程と違い「Number」プロパティを初期化しているが、これを省略するともちろんo1とは違う型になってしまい互換性はなくなる。また、型を推論できないので、プロパティの値にnullは指定できない。

ラムダ式

関数型言語でおなじみのラムダ式がついにサポートされた。

var intArray = new List<int> { 1, 2, 3, 4, 5 };

このリストの中の要素に対して特定の要素を取り出す場合、以前は匿名メソッドを用いて行っていた。

// 3を取り出す
int matchObj = intArray.Find(
    delegate(int i) { return i == 3; }
);

1.1に比べればはるかに簡潔だが、3.0ではさらに簡潔に書ける。

var matchObj = intArray.Find(i => i == 3);

ちなみにラムダ式も他と同様にvarでデリゲート型を省略できるかと思いきや、おもいっきりコンパイルエラーが出た。

// エラー
var func = i => i + 1;

こはちゃんとラムダ式と同じシグネチャを持つデリゲートを定義する必要がある。

delegate int Function(int value);
// 成功
Function func = i => i + 1;

LINQ

疲れたので寝る。