2010-01-15 42 views
2

我有邏輯的功能,看起來像這樣:模式:在函數退出時執行某些操作的優雅方法?

doStuff1() 
try: 
    doStuff2() 
except type1: 
    error1() 
    return endstuff() 
except type2: 
    error2() 
    return endstuff() 
except: 
    error3() 
    return endstuff() 

if doStuff3(): 
    error4() 
    return endstuff() 

doStuff4() 
return endstuff() 

正如你所看到的,是endstuff()在一切可能的退出功能來完成。現在,endstuff()實際上是兩行代碼,最近我不得不爲所有可能的退出添加第三行代碼。有沒有更優雅的方式來組織這些代碼?我不能只使用finally,因爲拋出異常並不總是這樣。

回答

10

可以即使沒有拋出任何異常,也可以使用最後一個,AFAIK這是最優雅的方式來做你想做的事。

+0

我知道,但這仍然會有3個重複 - 最後一個,if中的一個,以及函數結尾的一個。我可以將這3個變成一個實例嗎?如果endstuff()是5-6行仍然是重複的代碼行。你是說我把所有的代碼都放在一個單獨的try ... finally塊中? – Claudiu 2010-01-15 20:09:28

+0

heh我很蠢。你的意思最終不是我的'嘗試'的補充,而是圍繞着整個代碼。我也忘記了即使在函數退出時,終於可以調用。 – Claudiu 2010-11-29 21:42:30

2

對於要調用的finally塊,不需要拋出異常。該塊的整點是它可靠地調用總是。你可以使用這個。

1

A finally子句將執行,無論是否拋出異常,所以你可以將你的代碼包裝在try/catch/finally的多個層次中......(這是C#,因爲你沒有指定一個語言)

try 
{ 
    try 
    { 
     something(); 
    } 
    catch 
    { 
     // Err handler for something 
    } 
} 
finally 
{ 
     endstuff(); // this code always runs 
} 
+1

我認爲值得指出的是,甚至還有'try ... finally'結構,它們根本不需要* catch存在。這種語言結構只有在沒有捕獲到異常時纔會執行'finally'塊。你的代碼示例很好地演示了這一點。 – stakx 2010-01-15 19:42:36

0

由於每次都返回endstuff(),所以不必短路返回呼叫。該函數將返回endstuff(),無論發生什麼情況,爲什麼在每次檢查中放置該代碼?除非你不想做doStuff4()如果有錯誤。

更優雅的方式可能是在finally塊中執行endstuff()並將該值賦給變量,然後在最後返回該變量。

1

根據不同的語言,這是RAII的理想選擇。例如,在堆棧中分配一個對象,並在其析構函數中執行「endstuff()」;這樣它就會在範圍的最後被調用。

class something 
    def ~something() 
     darkside() 
     endstuff() 


// in the function 
def somefunc() 
    something s 

    doStuff1() 
    try: 
     doStuff2() 
    except type1: 
     error1() 
     return 
    except type2: 
     error2() 
     return 
    except: 
     error3() 
     return 

    if doStuff3(): 
     error4() 
     return 

    doStuff4() 
    return 

+0

@Claudiu雖然不支持GC語言,但... – 2010-04-16 17:55:16

1

我贊成finally塊,但只是作爲一種替代你可以使用一個while塊如:

while(true) 
    doStuff1() 
    try: 
     doStuff2() 
    except type1: 
     error1() 
     break 
    except type2: 
     error2() 
     break 
    except: 
     error3() 
     break 

    if doStuff3(): 
     error4() 
     break 

    doStuff4() 
end while 

return endstuff() 

,如果你使用的是做一個語言,這是有用不支持例外。在這種情況下,您的except type只會檢查上次返回結果的錯誤值。

0

關於'finally'子句的其他評論是正確的,但是當我沒有'finally'子句可用時(並非所有語言都可以),我將多退出代碼分解爲子功能。這不僅適用於try/catch,還適用於需要檢查許多條件並且要避免深度嵌套的'if'子句的代碼。這個例子顯示了兩個:

ThingOne() { 
    var foo; 
    foo.open(); 

    if (ThingTwo(foo)) 
     ThingThree(foo); 

    foo.close(); 
} 

ThingTwo(var x) { 
    try 
    { 
     ...normal case... 
     return true 
    catch x1 
     handlex1(); 
    catch x2 
     handlex2(); 
    } 
    return false; 
} 

ThingThree(var x) { 
    if (x.conditionOne == false) return; 
    if (x.conditionTwo == true) return; 
    ...etc... 
    x.GoForIt(); 
} 
相關問題