はい、ensureコードが常に評価されるようにします。それがと呼ばれる理由ensureです。したがって、JavaおよびC#と同等finallyです。
begin/ rescue/ else/ ensure/ の一般的なフローはend次のようになります。
begin
# something which might raise an exception
rescue SomeExceptionClass => some_variable
# code that deals with some exception
rescue SomeOtherException => some_other_variable
# code that deals with some other exception
else
# code that runs only if *no* exception was raised
ensure
# ensure that this code always runs, no matter what
# does not change the final value of the block
end
あなたは省くことができrescue、ensureまたはelse。変数を省略することもできます。その場合、例外処理コードで例外を検査できなくなります。(ええと、いつでもグローバル例外変数を使用して、発生した最後の例外にアクセスできますが、少しハッキーです。)そして、例外クラスを省略できます。この場合、継承元のすべての例外StandardErrorがキャッチされます。これはことを意味しないことを(してくださいノートすべてのインスタンスである例外があるので、例外がキャッチされているExceptionではないがStandardError。のようなプログラムの妥協整合性大抵非常に厳しい例外SystemStackError、NoMemoryError、SecurityError、NotImplementedError、LoadError、SyntaxError、ScriptError、Interrupt、SignalExceptionまたはSystemExit。)
一部のブロックは、暗黙の例外ブロックを形成します。たとえば、メソッド定義は暗黙的に例外ブロックでもあるため、次のように記述するのではなく
def foo
begin
# ...
rescue
# ...
end
end
あなたはただ書く
def foo
# ...
rescue
# ...
end
または
def foo
# ...
ensure
# ...
end
class定義やmodule定義についても同様です。
しかし、あなたが尋ねている特定のケースでは、実際にはもっと良いイディオムがあります。一般に、最後にクリーンアップする必要があるリソースを操作する場合は、すべてのクリーンアップを実行するメソッドにブロックを渡すことでそれを行います。これusingはC#のブロックに似ていますが、Rubyは実際には強力であり、Microsoftの大祭司が山から降りてきて、コンパイラーを丁寧に変更するのを待つ必要がありません。Rubyでは、自分で実装することができます。
# This is what you want to do:
File.open('myFile.txt', 'w') do |file|
file.puts content
end
# And this is how you might implement it:
def File.open(filename, mode='r', perm=nil, opt=nil)
yield filehandle = new(filename, mode, perm, opt)
ensure
filehandle&.close
end
そしてあなたは何を知っていますか:これはコアライブラリですでにとして利用可能ですFile.open。ただし、これは、任意の種類のリソースクリーンアップ(usingC#でのアラ)またはトランザクションなど、考えられるあらゆるものを実装するために、独自のコードでも使用できる一般的なパターンです。
これが機能しない唯一のケースは、リソースの取得と解放がプログラムのさまざまな部分に分散されている場合です。しかし、例のようにローカライズされている場合は、これらのリソースブロックを簡単に使用できます。
ところで、最近のC#では、usingRubyスタイルのリソースブロックを自分で実装できるため、実際には不要です。
class File
{
static T open<T>(string filename, string mode, Func<File, T> block)
{
var handle = new File(filename, mode);
try
{
return block(handle);
}
finally
{
handle.Dispose();
}
}
}
// Usage:
File.open("myFile.txt", "w", (file) =>
{
file.WriteLine(contents);
});
beginブロック内に置く必要があります。