構文はさておき、違いは何ですか
try {
}
catch() {
}
finally {
x = 3;
}
と
try {
}
catch() {
}
x = 3;
編集:.NET 2.0で?
それで
try {
throw something maybe
x = 3
}
catch (...) {
x = 3
}
行動的に同等ですか?
構文はさておき、違いは何ですか
try {
}
catch() {
}
finally {
x = 3;
}
と
try {
}
catch() {
}
x = 3;
編集:.NET 2.0で?
それで
try {
throw something maybe
x = 3
}
catch (...) {
x = 3
}
行動的に同等ですか?
まず、try ブロック内で RETURN を実行すると、finally は引き続き実行されますが、try-catch-finally ブロックの下にリストされているコードは実行されません。
若干のセマンティックの違いがあるかもしれないので、言語に依存しますが、try ブロックのコードが例外をスローした場合でも、(ほぼ) 常に実行されるという考え方です。
2 番目の例では、catch ブロック内のコードが戻るか終了する場合、x = 3 は実行されません。最初はそうなります。
.NET プラットフォームでは、finally ブロックの実行が発生しない場合があります: セキュリティ例外、スレッドの中断、コンピューターのシャットダウン :) など。
Java の場合:
最終的には、例外が catch() で正しくキャッチされたかどうかに関係なく、または実際に catch があるかどうかに関係なく、常に呼び出されます。
try catch finallyは非常に重要な構造です。例外がスローされても、finally ブロック内のコードが実行されることを確認できます。それらを解放するために外部リソースを処理することは非常に重要です。ガベージ コレクションはそれを行いません。最後に、returnステートメントを使用したり、例外をスローしたりしないでください。それを行うことは可能ですが、それは悪い習慣であり、予測できない結果につながる可能性があります。
この例を試す場合:
try {
return 0;
} finally {
return 2;
}
結果は2になります:)
他の言語との比較:最後から戻る
finally ブロックを便利にするいくつかのことがあります。
これらにより、finally ブロックは、ファイル ハンドルまたはソケットを閉じるのに優れたものになります。
try と catch が空の場合、違いはありません。それ以外の場合は、finally が実行されることを確認できます。
たとえば、catchblock で新しい Exception をスローする (rethrow) 場合、finally ブロックにある場合にのみ割り当てが実行されます。
通常、finally は自分の後でクリーンアップするために使用されます (DB 接続、ファイルハンドルなどを閉じます)。
最後にコントロール ステートメント (return、break、continue) を使用しないでください。
finally ブロックを使用すると、開発者として、try{} ブロック内の先行するコードのアクションでエラーが発生したかどうかに関係なく、自分自身を片付けることができます。これは、主にリソースの解放の傘下にあります。ポインター / ソケット / 結果セット、接続をプールに返すなど。
@mats は、常に「ハード」な障害が発生する可能性があるという点で非常に正しいです。finally ブロックにはミッション クリティカルなコードを含めるべきではありません。ミッション クリティカルなコードは、常に try 内でトランザクション的に実行する必要があります。{}
@mats 再び - 本当の美しさは、独自のメソッドから例外をスローできることです。
try
{
StreamReader stream = new StreamReader("foo.bar");
mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
//Swallow this
logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
//More serious, throw this one back
throw(e);
}
finally
{
stream.close();
}
したがって、多くの種類の例外をキャッチし、それらを異なる方法で処理できます (最初の例外では、try{} を超えるすべての実行が許可され、2 番目の例外では効果的に返されます) が、常にきちんと整然と片付けられます。
finally ブロックは、例外がスローされた場合や return ステートメントに到達した場合でも (言語に依存する場合がありますが)常に呼び出されます (実際には常にではありません)。これは、常に呼び出されることを知っていることをクリーンアップする方法です。
@iAn と @mats:
原則として、try {} 内で「設定」されたものを finally {} で「破棄」しません。try {} の外でストリームの作成をプルする方がよいでしょう。ストリームの作成時に例外を処理する必要がある場合、これはより広い範囲で行うことができます。
StreamReader stream = new StreamReader("foo.bar");
try {
mySendSomethingToStream(stream);
}
catch(noSomethingToSendException e) {
//Swallow this
logger.error(e.getMessage());
}
catch(anotherTypeOfException e) {
//More serious, throw this one back
throw(e);
}
finally {
stream.close();
}
未処理の例外が発生した場合でも、finally 内のすべてのコードが で実行されます。通常、finally コードは、.dispose() を使用してアンマネージ コードのローカル宣言をクリーンアップするために使用されます。
そのため、try ブロックで初期化された開いている接続などをクリーンアップできます。接続を開いた後に例外が発生した場合、その例外は適切に閉じられませんでした。このタイプのシナリオは、finally ブロックの目的です。
finally ブロックは、例外をキャッチしたかどうかに関係なく実行することになっています。Try/Catch/Finally の例を参照してください
@Edcatch(...)
、 C ++で指定されていない例外をキャッチするようなものを考えているかもしれません。
しかし、ブロックfinally
内で何が起こっても実行されるコードです。catch
Microsoft には、 C# の try-finallyに関するヘルプ ページがあります。
finally ブロックは try/catch と同じスコープにあるため、内部で定義されているすべての変数にアクセスできます。
ファイルハンドラーがあると想像してください。これは、それがどのように記述されるかの違いです。
try
{
StreamReader stream = new StreamReader("foo.bar");
stream.write("foo");
}
catch(Exception e) { } // ignore for now
finally
{
stream.close();
}
に比べ
StreamReader stream = null;
try
{
stream = new StreamReader("foo.bar");
stream.write("foo");
} catch(Exception e) {} // ignore
if (stream != null)
stream.close();
ただし、最終的には実行が保証されないことに注意してください。アボート信号を受信したり、ウィンドウがクラッシュしたり、電源が切れたりしたと想像してください。ビジネス クリティカルなコードを finally に依存するのは良くありません。
Java では、"return" を使用したか、try ブロックを実行しただけか、または例外をキャッチしたかに関係なく、実行したいものすべてに使用します。
たとえば、データベース セッションまたは JMS 接続を閉じたり、OS リソースの割り当てを解除したりします。
.NETでも似ていると思いますか?