はい、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
。ただし、これは、任意の種類のリソースクリーンアップ(using
C#でのアラ)またはトランザクションなど、考えられるあらゆるものを実装するために、独自のコードでも使用できる一般的なパターンです。
これが機能しない唯一のケースは、リソースの取得と解放がプログラムのさまざまな部分に分散されている場合です。しかし、例のようにローカライズされている場合は、これらのリソースブロックを簡単に使用できます。
ところで、最近のC#では、using
Rubyスタイルのリソースブロックを自分で実装できるため、実際には不要です。
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
ブロック内に置く必要があります。