2014-06-22 42 views
2

我需要在大量函數調用中以相同方式記錄錯誤。在這裏,我想從foo.create(...)File.new_tmp(...)的錯誤被記錄handle_error(...)我如何分解出使用try {...} catch(Error e){log_error(e);}

// compile with `valac --pkg gio-2.0 main.vala` 

void log_error(Error e) { 
    // error logging here 
} 

void main() { 
    var foo = File.new_for_path("foo"); 
    try { 
     foo.create(FileCreateFlags.NONE); 
    } catch (Error e) { 
     log_error(e); 
    } 

    FileIOStream tmp_stream; 
    try { 
     File.new_tmp(null, out tmp_stream); 
    } catch (Error e) { 
     log_error(e); 
    } 
} 

(是的,main應與FileIOStream東西,如果繼續失敗foo.create,這就是爲什麼他們在不同的try/catch塊。)

我要分解出使用try {...} catch (Error e) {log_error(e);}成功能如下所示:

delegate void Action(); 

void log_error(global::Action action) { 
    try { 
     action(); 
    } catch (Error e) { 
     // error logging here 
    } 
} 

void main() { 
    var foo = File.new_for_path("foo"); 
    log_error(() => foo.create(FileCreateFlags.NONE)); 

    FileIOStream tmp_stream; 
    log_error(() => File.new_tmp(null, out tmp_stream)); 
} 

但華劣克給予警告unhandled error 'GLib.IOError'因爲你似乎無法趕上在關閉時拋出的錯誤,我也不能只是將log_error(...)重寫爲#define宏,因爲vala不支持它們。那麼我能做什麼?

+0

@Crowder'new_for_path'不能根據[valadoc](http://references.valadoc.org/#!api=gio-2.0/GLib.File.new_for_path)拋出錯誤,但這只是一些無論如何,稍微複雜的示例代碼。 – mcjohnalds45

+0

@Crowder在我真正的應用程序中,我的錯誤處理代碼只是告訴用戶一些事情搞砸了,我不想讓人們閱讀大量無關的代碼。 – mcjohnalds45

+0

Oooooh我知道你的意思!我真的很抱歉,雖然你在嘲笑我無關緊要的事情。答案是否定的,當這些函數錯誤時'main'不需要返回。我已經編輯了這個問題,以減少愚蠢。 – mcjohnalds45

回答

2

你可以捕獲在閉包中拋出的異常,你只需要委託拋出異常。你想要什麼可能是這樣的:

public delegate T? Action<T>() throws GLib.Error; 

T? log_error<T> (global::Action<T> func) { 
    try { 
    return func(); 
    } catch (GLib.Error e) { 
    // error logging here 
    return null; 
    } 
} 

void main() { 
    var foo = File.new_for_path("foo"); 
    log_error<GLib.FileOutputStream> (() => foo.create (FileCreateFlags.NONE)); 

    FileIOStream? tmp_stream = null; 
    GLib.File? f = log_error<GLib.File> (() => File.new_tmp (null, out tmp_stream)); 
} 

請注意,我做了它一個通用的,因此可以實際使用的返回值。如果你想要它應該是微不足道的,以消除泛型類型的參數,只是返回void,但你會失去一些靈活性。

+0

'log_error '返回一個可爲空的'GLib.File'。在這種情況下,它應該是'GLib.File? f = log_error (...);',對吧? –

+0

是的,修好了,謝謝。 – nemequ