我需要在大量函数调用中以相同的方式记录错误。在这里,我希望由 handle_error(...)< 记录来自
.foo.create(...)
和 File.new_tmp(...)
的错误
// 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);
}
}
(是的,如果 foo.create
失败,main
应该继续使用 FileIOStream
内容,这就是为什么它们在单独的 try/catch
block 。)
我想将 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));
}
但是 valac 给出了警告 unhandled error 'GLib.IOError'
因为你似乎无法捕获闭包中抛出的错误,我也不能重写 log_error(...)
作为 #define
宏,因为 vala 不支持它们。那我能做什么呢?
最佳答案
你可以捕获闭包中抛出的异常,你只需要让委托(delegate)抛出异常即可。你想要的可能是这样的:
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 应该很简单,但您会失去一些灵活性。
关于error-handling - 如何分解我对 `try {...} catch (Error e) {log_error(e);}` 的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24349403/