C# をやることになった

C#.NET をやることになった。ちょっと古い C# 2.0 を使っているので 3.0 の型推論とかが無いのがちょっと残念だけど。

まだ初心者だけど、いまのところのお気に入り点

usingブロック

以下のように書くと、ブロックを抜けるときに、自動で引数に指定した変数の IDisposable#Dispose() メソッドを呼んでくれるというもの。*1

using (StreamReader reader = new StreamReader("file.txt"))
{
    // readerを使った処理...
}

上のコードはRubyのこれのようなもの。

File.open("file.txt") do |file|
  # file を使った処理...
end

delegate

Javaのように無名クラスを介さなくても、簡単に関数オブジェクトやクロージャのようなものが作れる。delegate は += で連結することもできる。

class Program
{
    delegate void TextWriterDelegate(TextWriter writer);

    static void Main(string[] args)
    {
        TextWriterDelegate testDelegate = CreateWriteLineDelegate("テスト");
        OutputToConsole(testDelegate);    // 「テスト」と表示
        testDelegate += CreateWriteLineDelegate("テスト2");
        OutputToConsole(testDelegate);    // 「テスト」「テスト2」と表示
    }

    static TextWriterDelegate CreateWriteLineDelegate(String text)
    {
        return delegate(TextWriter writer)
        {
            writer.WriteLine(text);
        };
    }

    static void OutputToConsole(TextWriterDelegate twDelegate)
    {
        twDelegate(Console.Out);
    }
}

GenericsがILレベルでサポートされている

JavaGenericsは単なるシンタックスシュガー・コンパイラのチェック機能で、コンパイル後のクラスファイルに型引数の情報が残らない。なので、たとえば

class Foo<T> {
    private Class clazz = T.class;
}

のようなことはできず、たとえばこんな場合などにちょっとダルいことになる。

C#ではILのレベルでGenericsをサポートしているので、

class Foo<T> {
    private Type type = typeof(T);
}

が可能。ほかにも値型のboxing/unboxingが発生しないなどのメリットがある。

コンパイル後のIL(中間言語)が確認しやすい

ILDasm.exe というGUIの逆アセンブラが標準でついていて、ILレベルでどういう処理をしているかわかりやすく確認できる。

逆にダメな点

Microsoft製の)標準ライブラリのソースが確認できない。これが最悪。

あとは、コレクション関係のライブラリが貧弱なこと。SortedList を逆順にすることすら こんな手順 が必要って本当なんだろうか……。

*1:Stream などを対象にした場合に Dispose() と Close() が全く同じなのかどうかはドキュメントに書いてない。ただ、確認した限りでは同じらしい。