[解決済み] なぜC#では'nullを投げる'ことができるのか?
質問
特に複雑な例外処理コードを書いているとき、ある人が、例外オブジェクトがヌルでないことを確認する必要はないのですか、と尋ねました。 そして私は、もちろん必要ないと言いましたが、その後、試してみることにしました。 どうやら、null を投げることはできますが、それはまだどこかで例外に変わります。
なぜこれが許されるのでしょうか?
throw null;
このスニペットでは、ありがたいことに'ex'はnullではありませんが、果たしてそうでしょうか?
try
{
throw null;
}
catch (Exception ex)
{
//can ex ever be null?
//thankfully, it isn't null, but is
//ex is System.NullReferenceException
}
どのように解決するのですか?
言語仕様では、型が
System.Exception
がある(したがって
null
はそのコンテキストでは有効です)、この式が非NULLであることを制限していません。一般に、その式の値が
null
であるかどうかを検出することはできません。halting problemを解決しなければならないだろう。ランタイムは
null
のケースを扱わなければならない。見てください。
Exception ex = null;
if (conditionThatDependsOnSomeInput)
ex = new Exception();
throw ex;
を投げるという具体的なケースを作ることも、もちろんできるだろう。
null
リテラルを無効とすることもできますが、それではあまり意味がありませんし、わずかな利益のために仕様スペースを浪費し、一貫性を低下させるのはいかがなものでしょうか。
免責事項(Eric Lippertに叩かれる前に)。これは 私自身の の推測に過ぎません。もちろん、私は設計会議に出席したことはありません ;)
2つ目の質問、catch節内でキャッチされた式変数は絶対にnullになることがあるのか、に対する回答です。C#の仕様では、他の言語がcatch節で捕捉された式変数をnullにできるかどうかについては言及されていません。
null
例外を伝播させることができるかどうかについて、C#の仕様は沈黙していますが、例外を伝播させる方法は定義しています。
catch節は、もしあれば、例外に適したハンドラを見つけるために、出現順に調べられます。最初のcatch節は で、例外の型または例外の型の基底型を指定します。 はマッチするとみなされます。一般的なcatch節は、どのような例外型に対してもマッチするとみなされます。[...]
については
null
については、太字の記述は誤りです。したがって、C# の仕様に純粋に基づくと、基礎となるランタイムが決して null を投げないとは言えませんが、たとえそうであったとしても、それは一般的な
catch {}
節によってのみ処理されることを確認できます。
CLI上のC#実装については、ECMA 335仕様を参照することができます。その文書では、CLIが内部で投げるすべての例外を定義しています(いずれも
null
によって投げられるユーザー定義の例外オブジェクトについて言及しています。
throw
命令で投げられることに言及しています。その命令に対する記述は、実質的にC#の
throw
文とほぼ同じです(オブジェクトの型を制限しないことを除けば
System.Exception
):
説明
は
throw
命令は例外オブジェクトを投げます (タイプO
) を投げ、スタックを空にする。例外の仕組みの詳細については、Partition Iを参照してください。
[注:CLIではどのようなオブジェクトでも投げることができるが、CLSでは言語の相互運用性のために使用しなければならない特定の例外クラスが記述されている。 注を終了する]。例外です。
System.NullReferenceException
が投げられた場合obj
はnull
.正しさ
正しいCILは、オブジェクトが常に以下のいずれかであることを保証します。
null
またはオブジェクトの参照(つまり、型O
).
捕捉された例外は決して
null
.
関連
-
[解決済み】C# - パスに不正な文字がある場合
-
[解決済み] [Solved] 不正な文字列値: '\xEFxBFxBD' for column
-
[解決済み] 投げる」と「投げる元」は違うのですか?
-
[解決済み] C#の[Flags]Enum属性の意味とは?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] Pythonの関数が例外を投げるかどうかをテストするにはどうすればよいですか?
-
[解決済み] Rubyで「例外 => e」を救済するのはなぜ悪いスタイルなのですか?
-
[解決済み】なぜFunc<T>ではなくExpression<Func<T>を使うのですか?
-
[解決済み】C#で例外をキャッチして再スローする理由とは?
-
[解決済み】WPFアプリケーションで例外をグローバルにキャッチする?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] エンティティタイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み] エンティティタイプ <type> は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】WPFでXamlファイルにコメントを追加する方法は?
-
[解決済み] 'IEnumerable<SelectListItem>' 型の ViewData アイテムで、キーが国であるものは存在しない。
-
[解決済み] UnityでOnCollisionEnterが呼ばれない
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み】エラー「必要なフォーマルパラメータに対応する引数が与えられていない」を解決する?
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み】なぜJavaでnullを投げることができるのですか?[重複)。