例外処理内のreturnについて
Rubyの例外処理のreturnについてのメモ。
rescue節内でのreturn
まずはrescue節内でのreturnです。
class Return
def test
begin
p "Begin"
1/0
return "return begin"
rescue => ex
p "Rescue"
return "return rescue"
ensure
p ex
p "Ensure"
end
end
end
obj = Return.new
p obj.test
実行結果がこちら
"Begin"
"Rescue"
#<ZeroDivisionError: divided by 0>
"Ensure"
"return rescue"
実行順として、
1. begin
2. rescue
3. ensure
4. return(rescue)
の流れになっており、rescue節内で処理が終了していることがわかります。
なお、begin~rescue~end
内のスコープは同じなので、ensure節からrescue節の変数(オブジェクト)が見えています。
ensure節内でのreturn
次に、ensure節内でreturnです。
class Return
def test
begin
p "Begin"
1/0
return "return begin"
rescue => ex
p "Rescue"
ensure
p ex
p "Ensure"
return "return ensure"
end
end
end
obj = Return.new
p obj.test
実行結果がこちら
"Begin"
"Rescue"
#<ZeroDivisionError: divided by 0>
"Ensure"
"return ensure"
実行順として、
1. begin
2. rescue
3. ensure
4. return(ensure)
の流れになっており、ensure節内で処理が終了していることがわかります。
rescue節内・ensure節内でのreturn
最後に、rescue節内・ensure節内でのreturnについてです。
class Return
def test
begin
p "Begin"
1/0
return "return begin"
rescue => ex
p "Rescue"
return "return rescue"
ensure
p ex
p "Ensure"
return "return ensure"
end
end
end
obj = Return.new
p obj.test
実行結果はこちら
"Begin"
"Rescue"
#<ZeroDivisionError: divided by 0>
"Ensure"
"return ensure"
実行順として、
1. begin
2. rescue
3. ensure
4. return(ensure)
の流れになっており、rescue内のreturnが実行されずにensure内のreturnで処理が終了していることがわかります。
また、rescue節を省いて例外を発生させない場合も考えて見ます。
class Return
def test
begin
p "Begin"
return "return begin"
ensure
p "Ensure"
return "return ensure"
end
end
end
obj = Return.new
p obj.test
実行結果はこちら。
"Begin"
"Ensure"
"return ensure"
実行順としては、
1. begin
2. ensure
3. return(ensure)
となっており、begin節内のreturnは実行されず、ensure節内で処理が終了しています。
結論
上記からもわかるように、ensure内にreturn文を記述すると、その時点で処理が終了してしまうため、本来期待していた処理が行われません。
このため、ensure節内でのreturnは避けるべきです。