C#のcatchがちょっと面白い

最近C#をちょっと書いているのだが、まったく未知のところからやっているとつい変なコードを書いてしまう。

先日は、こんなコードを書いた。

using System; // for Exception

class Program
{
    private static void Main() {
        try {
            throw new Exception("error!");
        }
        catch (Exception) {
        }
    }
}

見ての通り、catch句に受け取る型名しか書いていない。なんでこんなことが起きるのかとTwitterでつぶやいたら、こんな感じで教えていただいた。

実用的には、あるクラスの例外だけ再スローして、ほかの例外は処理する、などに使えるのだろう。

using System;

class ExceptionA : Exception
{
    // 関係ないけどコンストラクタいちいち書かないといけないのなんとかならんの?
    public ExceptionA(string message) : base(message) {
    }
}

class Program
{
    private static void Main() {
        try {
            throw new ExceptionA("error!");
        }
        catch (ExceptionA) {
            // こうすると再スローできる
            throw;
        }
        catch (Exception e) {
            // ExceptionA以外のExceptionクラスの例外は、処理する
            Console.Write(e);
        }
        // こうすると残りぜんぶ取れる
        catch {
        }
    }
}

型のゆるい言語を使っていると、catchした後にクラスを見て処理とか考えてしまうが、型の厳しい言語ではこういうやり方があるのだろう。

型の厳しい言語はほとんど使ったことがないので勉強になる。

追記

タイトルをちょっと修正した。メソッドじゃないのにcatch()とかおかしかったので。

メソッドといえば、メソッドのパラメータにクラス・型だけ書くのはできないようだ。まあ、意味ないしね。

// コンパイルすると、
// ... error CS1001: ID がありません。
// となる。
using System;

class Program
{
    private static void Main() {
    }

    private void Method(Exception) {
    }
}