時々私はこれを行い、他の人もそれをしているのを見ました:
Try
DontWannaCatchIt()
Catch
End Try
try
{
DontWannaCatchIt();
}
catch {}
私はすべての重要な例外をキャッチする必要があることを知っています私が期待していることそしてそれについて何かをします、しかし時にはそれが重要ではない-または私は何か間違ったことをしていますか?
このtry
ブロックの使用法は正しくありませんか。また、少なくとも1つのcatch
またはfinally
ブロックが必要であることを示していますか?
今、私はこれの理由を理解しました、そしてそれは私が少なくとも空のcatchブロックについてコメントすべきであるので、他の人がそれが空である理由を理解します。また、期待している例外のみをキャッチする必要もあります。
幸運なことに、私はVBでコーディングしているので、1つのキャッチでそれを書くことができます:
Catch ex As Exception When TypeOf ex Is IOException _
OrElse TypeOf ex Is ArgumentException _
OrElse TypeOf ex Is NotSupportedException _
OrElse TypeOf ex Is SecurityException _
OrElse TypeOf ex Is UnauthorizedAccessException
'I don't actually care.
End Try
キャッチしたくない場合、なぜ最初にtry
を使用するのですか?
try
ステートメントは、問題が発生する可能性があると考えていることを意味し、catch
は、問題が発生した場合に適切に対処できると述べています。
だからあなたの推定では:
try
{
//Something that can go wrong
}
catch
{
//An empty catch means I can handle whatever goes wrong. If a meteorite hits the
//datacenter, I can handle it.
}
そのキャッチは、発生するすべての例外を飲み込みます。あなたはあなたのコードで処理できる自信がありますかanythingそれは優雅にうまくいきませんか?
(あなたとあなたのメンテナンスプログラマーの両方の健全性のために)最善の方法は、正常に処理できることを明示的に示すことです。
try
{
//Something that could throw MeteoriteHitDatacenterException
}
catch (MeteoriteHitDatacenterException ex)
{
//Please log when you're just catching something. Especially if the catch statement has side effects. Trust me.
ErrorLog.Log(ex, "Just logging so that I have something to check later on if this happens.")
}
いいえ、重要ですnotすべての重要な例外をキャッチしてください。修正する方法がなく、ユーザーに報告する必要がない場合は、I/Oエラーなど、気にしない例外をキャッチして無視してもかまいません。
ただし、StackOverflowException
やOutOfMemoryException
などの例外を伝播させる必要があります。または、より一般的には、NullReferenceException
です。これらの例外は通常、予期していなかったエラーから回復できません回復すべきではない回復できないため、抑制しないでください。
例外を無視したい場合は、その特定の例外のコードに空のcatchブロックを明示的に書き込むのがgoodです。これにより、無視している例外が明確になります。例外を非常に正しく無視するのはオプトイン手順であり、オプトアウト手順ではありません。特定のタイプを無視しないようにオーバーライドできる「すべての例外を無視する」機能を持つことは、非常に悪い言語機能です。
どのタイプの例外が重要で、キャッチされるべきでないかをどのようにして知るのですか?知らない例外がある場合はどうなりますか?慣れていない重要なエラーを抑制しないことをどうやって知っていますか?
try
{
}
// I don't care about exceptions.
catch
{
}
// Okay, well, except for system errors like out of memory or stack overflow.
// I need to let those propagate.
catch (SystemException exception)
{
// Unless this is an I/O exception, which I don't care about.
if (exception is IOException)
{
// Ignore.
}
else
{
throw;
}
}
// Or lock recursion exceptions, whatever those are... Probably shouldn't hide those.
catch (LockRecursionException exception)
{
throw;
}
// Or, uh, what else? What am I missing?
catch (???)
{
}
キャッチがないか、最終的には無効です。空のcatchまたは最終的には有効です。空のキャッチは、例外を気にしないことを意味します。何かを実行しようとするだけで、機能しないかどうかは関係ありません。続行したいだけです。たとえば、クリーンアップ関数で役立ちます。
また、エラーについて何かをする必要がない場合は、プログラムが無視する必要がある例外の種類を指定する必要があります。
すべての例外を無視する必要がある場合は、このようにtry/catchを使用できない理由がわかりません。
通常は間違いです。例外はまあ、例外的な動作を示します;例外がスローされた場合、何か問題が発生したことを意味します。したがって、何も問題がなかったかのように通常のプログラムフローを続行することは、エラーを隠す方法であり、一種の拒否です。代わりに、コードが例外的なケースをどのように処理するかを考え、それを実現するコードを記述してください。カバーしたために伝播するエラーはmuchすぐに現れるエラーよりもデバッグが困難です。
大多数の開発者は悪い習慣と見なしているので、簡単にはできません。
誰かが後でDontWannaCatchIt()
の本体にメソッド呼び出しを追加すると、doesキャッチする価値のある例外がスローされますが、空のcatchブロックによって飲み込まれる場合はどうなりますか?実際にキャッチしたいが、現時点ではそれを認識していない例外がある場合はどうなりますか?
これを絶対に行う必要がある場合は、キャッチする例外のタイプをできるだけ具体的に指定してください。そうでない場合は、おそらく例外のロギングがオプションです。
エラーが存在し、スローされており、どこかに移動する必要があります。通常のコードフローが中止され、ファンをクリーニングする必要があります。
キャッチブロックなし=不確定な状態。コードはどこに行くべきですか?どうする?
空のcatchブロック=エラーを無視して処理されます。
注:VBAには「On Error Continue」という悪質なものがあります...
私が聞いた理由は、何らかの理由で試行が失敗した場合、エラー応答を制御できるようにすることは、フレームワークが制御できるようにすること(つまり、黄色の画面やエラー500)よりも非常に好ましいということです。
あなたがtryでコードだけを書くとどうなりますか
try
{
int j =0;
5/j;
}
これは書くことと同等です
int j =0;
5/j;
したがって、tryと書いても意味がありません。行数が増えるだけです。
空のcatchまたはfinallyでtryと書いた場合、ランタイムに異なる動作をするよう明示的に指示しています。
そのため、空のtryブロックは不可能だと思います。
はい、不正解です。 goto
のようなものです:100 KLocごとに1つで十分ですが、これらの多くが必要な場合は、間違っています。
反応なしで例外を飲み込むことは、エラー処理の最悪の事態の1つであり、少なくとも明示的に行う必要があります。
_try
{
DontWannaCatchIt();
}
catch
{
// This exception is ignored based on Spec Ref. 7.2.a,
// the user gets a failure report from the actual results,
// and diagnostic details are available in the event log (as for every exception)
}
_
さらに遠くに見える:
エラー処理は側面です。一部のコンテキストでは、エラーがスローされ、コールスタックまで伝播する必要があります(たとえば、ファイルをコピーする、コピーが失敗する)。
異なるコンテキストで同じコードを呼び出すと、エラーの追跡が必要になる場合がありますが、操作は続行されます(たとえば、100個のファイルをコピーし、どのファイルが失敗したかを示すログが記録されます)。
この場合でも、空のキャッチハンドラは間違っています。
ほとんどの言語では、ループ内でtry + catchを実行し、catchハンドラーでログを作成する以外に直接的な実装はありません。 (ただし、mroeの柔軟なメカニズムを構築することもできます。メッセージをスローしたり、隠したりできる呼び出しごとのスレッドハンドラーを用意してください。ただし、デバッグツールとのやり取りは、直接的な言語サポートがなければ困難です。)
賢明なユースケースはTryX()
からX()
を実装することですが、問題の例外を返す必要があります。