私は入れ子になった try/catch ステートメントについて考えてきましたが、JIT がコンパイルされた IL の最適化または単純化を実行できる条件があるとすれば、それについて考え始めました。
説明のために、例外ハンドラの次の機能的に同等の表現を考えてみましょう。
// Nested try/catch
try
{
try
{
try
{
foo();
}
catch(ExceptionTypeA) { }
}
catch(ExceptionTypeB) { }
}
catch(ExceptionTypeC) { }
// Linear try/catch
try
{
foo();
}
catch(ExceptionTypeA) { }
catch(ExceptionTypeB) { }
catch(ExceptionTypeC) { }
ネストされた try ステートメントのスタック フレーム内に追加の変数参照や関数呼び出しがないと仮定すると、JIT は、スタック フレームが線形の例に折りたたまれている可能性があると結論付けることができますか?
では、次の例はどうでしょうか。
void Try<TException>(Action action)
{
try
{
action();
}
catch (TException) { }
}
void Main()
{
Try<ExceptionC>(Try<ExceptionB>(Try<ExceptionA>(foo)));
}
JIT がデリゲート呼び出しをインライン化する方法はないと思うので、この例を前の例に還元することはできません。ただし、 をfoo()
スローExceptionC
した場合、線形の例と比較して、このソリューションのパフォーマンスは低下しますか? フレームに含まれる余分なデータは最小限ですが、デリゲートの呼び出しからスタック フレームを破棄するには余分なコストがかかると思います。