[解決済み] RubyでBegin, Rescue, Ensure?
質問
最近、Rubyでプログラミングを始めたのですが、例外処理について調べています。
と思っていたら
ensure
はRubyの
finally
をC#で使うか?した方がいいのでしょうか。
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
rescue
#handle the error here
ensure
file.close unless file.nil?
end
とか、こうすればいいのか?
#store the file
file = File.open("myFile.txt", "w")
begin
file << "#{content} \n"
file.close
rescue
#handle the error here
ensure
file.close unless file.nil?
end
は
ensure
は、例外が発生しなくても、何があっても呼び出されるのでしょうか?
解決方法は?
はい。
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
ただし、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
. しかし、これはあなた自身のコードにも使える一般的なパターンであり、あらゆる種類のリソースのクリーンアップを実装することができます(à la
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);
});
関連
-
[解決済み】Ruby: 特定のバージョンのruby gemをインストールする方法は?
-
[解決済み】コレクションをDESCで並べる方法
-
[解決済み] Rubyのswitch文の書き方
-
[解決済み] Ruby on Railsのマイグレーションでデータベースのカラムの名前を変更するにはどうすればよいですか?
-
[解決済み] Rubyで配列に値が存在するかどうかを確認する方法
-
[解決済み] Rubyからシェルコマンドを呼び出す方法
-
[解決済み] Rubyでnilとemptyとblankを理解する方法
-
[解決済み] Rubyのattr_accessorとは何ですか?
-
[解決済み] Ruby on Railsで現在の絶対URLを取得するにはどうすればよいですか?
-
[解決済み] Rubyで「例外 => e」を救済するのはなぜ悪いスタイルなのですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】なぜRuby on Railsは、http://localhost:3000 の代わりに http://0.0.0.0:3000 を使用するのですか?
-
[解決済み】TypeError: SymbolからIntegerへの暗黙の変換がない。
-
[解決済み] デバイスを使用する現在のユーザーメソッド
-
[解決済み] Errno::EACCESS: パーミッションが拒否された @ dir_s_mkdir
-
[解決済み] Ruby:Rubyの配列にinclude.の反対はある?
-
[解決済み] サーバーはRailsで既に稼働している
-
[解決済み] Rspec が私のモデルクラスを認識しない。初期化されていない定数エラー
-
[解決済み] Ruby on rails アプリで ES6 (ES2015) を使用するにはどうすればよいですか?
-
[解決済み] rails/rubyでgroup_byを使用する。
-
[解決済み] 属性とカラムの違いは何ですか?