최근에 Ruby로 프로그래밍을 시작했으며 예외 처리를보고 있습니다.
C #에서 ensure
Ruby와 동등한 지 궁금합니다 finally
. 내가해야 :
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
루비는 실제로 Microsoft의 대제사장이 산에서 내려 와서 컴파일러를 자비 롭게 바꿀 때까지 기다릴 필요가 없을 정도로 강력하다는 점을 제외하면 C # 의 블록 과 비슷 합니다. 루비에서는 직접 구현할 수 있습니다.
# 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 #에서 la ) 또는 트랜잭션 또는 생각할 수있는 모든 것을 구현하기 위해 자신의 코드에서도 사용할 수있는 일반적인 패턴 입니다.
리소스를 확보하고 해제하는 것이 프로그램의 다른 부분에 분산되어있는 경우 이것이 작동하지 않는 유일한 경우입니다. 그러나 예제와 같이 현지화 된 경우 이러한 리소스 블록을 쉽게 사용할 수 있습니다.
BTW : 현대 C #에서는 using
루비 스타일의 리소스 블록을 직접 구현할 수 있기 때문에 실제로 불필요합니다.
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);
});
답변
참고로, rescue
섹션 에서 예외가 다시 발생 ensure
하더라도 코드 실행이 다음 예외 핸들러로 계속 진행되기 전에 블록이 실행됩니다. 예를 들어 :
begin
raise "Error!!"
rescue
puts "test1"
raise # Reraise exception
ensure
puts "Ensure block"
end
답변
파일을 닫으려면 다음 형식의 블록을 사용해야합니다 File.open
.
File.open("myFile.txt", "w") do |file|
begin
file << "#{content} \n"
rescue
#handle the error here
end
end
답변
예, ensure
어떤 상황에서도 부름을받습니다. 자세한 정보 는 Programming Ruby 서적의 ” 예외, 캐치 및 처리 “를 참조하고 “확인”을 검색하십시오.
답변
예, ensure
매번 실행되므로 블록 file.close
에서 필요하지 않습니다 begin
.
그런데 테스트하는 좋은 방법은 다음과 같습니다.
begin
# Raise an error here
raise "Error!!"
rescue
#handle the error here
ensure
p "=========inside ensure block"
end
예외가있을 때 “========= 내부 블록 확인”이 인쇄되는지 테스트 할 수 있습니다. 그런 다음 오류를 발생시키는 명령문을 주석 처리하고 ensure
인쇄 된 것이 있는지 확인하여 명령문이 실행되는지 확인할 수 있습니다.
답변
이것이 우리에게 필요한 이유입니다 ensure
.
def hoge
begin
raise
rescue
raise # raise again
ensure
puts 'ensure' # will be executed
end
puts 'end of func' # never be executed
end
답변
예, ensure
같은 finally
보장 블록이 실행됩니다 . 이는 오류시 파일 핸들을 닫거나 뮤텍스를 해제하는 등 중요한 리소스를 보호하는 데 매우 유용합니다.