ruby中的异常处理机制分析

ruby是一门动态脚本语言,这个大家都知道。

我今天想讨论的问题是ruby中的异常处理机制,首先贴一段代码:

1 class SocketError < StandardError

2 end

3

4 class Test

5 @host = "192.168.0.1"

6 @port = 8000

7 def opensocket

8 ret_str = "socket open Fail"

9 begin

10 socket = TCPSocket.open(@host,@port)

11 ret_str = "socket open successed!"

12 rescue => e

13 puts "socket error"

14 raise SocketError

15 end

16 return ret_str

17 end

18 end

19

20 #############################

21 t = Test.new

22 begin

23 str = t.opensocket()

24 puts str

25 rescue SocketError

26 puts "socket open fail in opensocket method"

27 end

28 #############################

这段代码打印的结果大家都应该会知道:

socket error

socket open fail in opensocket method

在看下下面的这段代码

1 class SocketError < StandardError

2 end

3

4 class Test

5 @host = "192.168.0.1"

6 @port = 8000

7 def opensocket

8 ret_str = "socket open Fail"

9 begin

10 socket = TCPSocket.open(@host,@port)

11 ret_str = "socket open successed!"

12 rescue => e

13 puts "socket error"

14 raise SocketError

15 ensure

16 return ret_str

17 end

18 end

19 end

20

21 #############################

22 t = Test.new

23 begin

24 str = t.opensocket()

25 puts str

26 rescue SocketError

27 puts "socket open fail in opensocket method"

28 end

29 #############################

30

31

大家说这段代码返回的是什么?

还是和上面的代码返回的结果一致么?

结果是:

socket error

socket open Fail

大家可能想“为什么他能返回的结果是:socket open Fail ,在在外层的resure中为什么不能接收到异常呢?为什么不能打印 socket open fail in opensocket method“

今天要讨论的问题就是这个。

在第二段代码与第一段代码的不同就是:return 语句放置 的位置不同。在第二段代码中吧return 放在 ensure中 ,第一段代码则是放置在 begin ... end语言之后。

其实就是这点的原因导致了上面的结果。在代码段2中,我们只是在是希望在异常的善后处理中能把我们想要的值返回去。

这样做将导致一个结果就是,在之前的rescue中raise 的异常将因为这个return而被”吃“掉。 也就是说,这个时候的他就不把raise 这个异常往上抛了,自己处理了,

其实在强类型语言里是不允许在ensure中return的。

例如在C#语言中,在try...catch...finally 的 finally中是不允许有return的,这样就避免了这样的问题发生。