言語仕様はSystem.Exception
そこで型の式を期待し(したがって、null
そのコンテキストで有効です)、この式がnull以外になることを制限しないためです。一般に、その式の値がそうであるかどうかを検出する方法はありnull
ません。停止性問題を解決する必要があります。null
とにかく、ランタイムはケースに対処する必要があります。見る:
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
もちろん、null
リテラルをスローする特定のケースを無効にすることはできますが、それはあまり役に立ちません。それでは、なぜ仕様スペースを無駄にし、一貫性を減らしてほとんど利益がないのでしょうか。
免責事項(Eric Lippertに叩かれる前):これは、この設計上の決定の背後にある理由についての私自身の推測です。もちろん、私はデザインミーティングに参加していません;)
2番目の質問に対する答えは、catch句内でキャッチされた式変数がnullになる可能性があるかどうかです。C#仕様では、他の言語でnull
例外が伝播されるかどうかについては言及されていませんが、例外が伝播される方法は定義されています。
キャッチ句がある場合は、出現順に調べて、例外に適したハンドラーを見つけます。例外タイプまたは例外タイプの基本タイプを指定する最初のcatch句は、一致と見なされます。一般的なcatch句は、すべての例外タイプに一致すると見なされます。[...]
の場合null
、太字のステートメントは誤りです。したがって、純粋にC#仕様の内容に基づいていますが、基になるランタイムがnullをスローしないとは言えませんが、その場合でも、genericcatch {}
句によってのみ処理されると確信できます。
CLIでのC#実装については、ECMA335仕様を参照できます。このドキュメントでは、CLIが内部でスローするすべての例外(いずれもnull
)を定義し、ユーザー定義の例外オブジェクトがthrow
命令によってスローされることに言及しています。その命令の説明は、C#throw
ステートメントと実質的に同じです(オブジェクトのタイプをに制限しないことを除いてSystem.Exception
):
説明:
このthrow
命令は、例外オブジェクト(type O
)をスタックにスローし、スタックを空にします。例外メカニズムの詳細については、パーティションIを参照してください。
[注:CLIはすべてのオブジェクトのスローを許可しますが、CLSは、言語の相互運用性に使用される特定の例外クラスを記述します。エンドノート]
例外:
System.NullReferenceException
場合にスローされてobj
いますnull
。
正しさ:
正しいCILは、オブジェクトが常にnull
またはオブジェクト参照(つまり、タイプO
)であることを保証します。
キャッチされた例外は決してないと結論付けるには、これらで十分だと思いますnull
。