Exceptionから継承しない値のthrow

C#ではExceptionクラスもしくは、その派生クラスしかthrow出来ませんが、C++/CLIだとそれ以外の値もスロー可能です。

// This is the main DLL file.

#include "stdafx.h"
#include "MyDLL2.h"

public ref class Foo {
public:
    static int Divide(int x, int y)
    {
        if (y == 0)
            // throw gcnew System::Exception();
            throw gcnew System::Int32();
            // throw -1;

        return x / y;
    }
};

上記のようなコードをコメントアウト部分を変えながらC#側でキャッチするとどうなるでしょうか?

using System;
using System.Runtime.InteropServices;

class Program
{
    static void Main (string[] args)
    {
        try
        {
            Foo.Divide (0,0);
        }
        catch (System.Runtime.CompilerServices.RuntimeWrappedException ex)
        {
            // throw gcnew System::Int32()はここ
        }
        catch (SEHException ex)
        {
            // throw -1はここ

        }
        catch (Exception ex)
        {
            // throw gcnew System::Exception()はもちろんここ
        }
        catch
        {
            // 引数なしのcatchブロックはC#1.0互換用
            // C#2.0からはExceptionから継承していない例外値は
            // RuntimeWrappedExceptionで包まれるようになった
        }
    }
}

こんな結果に。C#1.0時代は引数なしのcatchを使って全ての例外をキャッチしたりしていましたが、C#2.0ではInt32など、Exceptionクラスから継承していない値が投げられるとRuntimeWrappedExceptionにラップされるので、全ての例外はExceptionでキャッチできます。と、いうことで引数なしのcatchはC#1.0の名残として、C#2.0以降は使わないようにしましょう。