当使用具有try/catch/finally的语言时,D的失败/成功/退出范围语句是否仍然有用?D似乎没有最终可以解释为什么在D中使用这些语句.但是使用像C#这样的语言是否有用?我正在设计一种语言,所以如果我看到很多专业人士,我会加入它.
DK.*_*DK. 39
scope(X)没有必要以不必要的方式for提供,只要你有if和goto.
这是我今天写的一些代码中的一个释义示例:
sqlite3* db;
sqlite3_open("some.db", &db);
scope(exit) sqlite3_close(db);
sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, "SELECT * FROM foo;", &stmt);
scope(exit) sqlite3_finalize(stmt);
// Lots of stuff...
scope(failure) rollback_to(current_state);
make_changes_with(stmt);
// More stuff...
return;
Run Code Online (Sandbox Code Playgroud)
与使用try/catch对比:
sqlite3* db;
sqlite3_open("some.db", &db);
try
{
sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, "SELECT * FROM foo;", &stmt);
try
{
// Lots of stuff...
try
{
make_changes_with(stmt);
// More stuff...
}
catch( Exception e )
{
rollback_to(current_state);
throw;
}
}
finally
{
sqlite3_finalize(stmt);
}
}
finally
{
sqlite3_close(db);
}
Run Code Online (Sandbox Code Playgroud)
代码变成意大利面条,在整个商店中传播错误恢复,并强制每个尝试块的缩进级别.在我看来,使用范围(X)的版本更易读,更容易理解.
try/catch /最终强制嵌套; 范围守卫没有.此外,它们允许您在与分配代码相同的"区域"中编写清理代码,因此不再需要"打开文件,滚动到功能结束,关闭文件,滚动到功能顶部".
从根本上说,虽然,这只是一个的try/catch /终于异常处理更加方便的表达- 任何你可以用的try/catch做/终于可以与范围卫士做,和反向.
这值得么?我是一个D粉丝(所以,有偏见),但我肯定会说.
免责声明我也是D粉丝男孩.
someRiskyFunctionThatMayThrow();
lock();
/* we have definitly got the lock so lets active
a piece of code for exit */
scope(exit)
freelock();
Run Code Online (Sandbox Code Playgroud)
相比:
try
{
someRiskyFunctionThatMayThrow();
lock();
}
finally
{
freeLockIfNotGot();
}
Run Code Online (Sandbox Code Playgroud)
区分失败 - 退出和成功退出在某些时候是非常有用的 - 我没有D的真实世界经验,但是Python的with声明也允许这样做,并且我发现它非常有用,例如,提交或回滚数据库在受保护的身体部分打开的交易.
当我解释这个新的Python特性(它现在已经存在一段时间了;-)给了C++和Java大师的朋友和同事时我发现他们立即理解了,并且看到了对这样一个特性的兴趣(Python确实有finally同样,但这对于区分成功与失败没有任何帮助,就像在其他语言中一样[或者C++的"RAII破坏块中的自动变量"等同于]).
值得一提的是,范围(退出),范围(失败)和范围(成功)也可用于C++.
支持以下语法,案例1:
try
{
int some_var=1;
cout << "Case #1: stack unwinding" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
throw 1;
} catch(int){}
Run Code Online (Sandbox Code Playgroud)
打印:
Case #1: stack unwinding
failure 1
exit 2
Run Code Online (Sandbox Code Playgroud)
案例2:
{
int some_var=1;
cout << "Case #2: normal exit" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
}
Run Code Online (Sandbox Code Playgroud)
打印:
Case #2: normal exit
success 1
exit 2
Run Code Online (Sandbox Code Playgroud)