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以降は使わないようにしましょう。