在Python中,有一个有用的异常处理代码:
try:
# Code that could raise an exception
except Exception:
# Exception handling
else:
# Code to execute if the try block DID NOT fail
我认为能够将可以引发的代码与普通代码中的异常分开是有用的。在Python中,这可能如上所示,但是我在C#中找不到类似的东西。
假设该功能或类似功能不存在,将常规代码放在try
块中或catch
块之后是标准做法吗?
我问的原因是因为我有以下代码:
if (!IsReadOnly)
{
T newobj;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
}
这需要普通代码在try块中,否则如果引发异常并随后处理,newobj
将被取消分配,但是在try块中包含这么多代码感觉非常不自然与DataPortalException
无关。怎么办?
由于
答案 0 :(得分:9)
我更希望看到try / catch之外的其余代码,因此很清楚你试图捕获的异常来自哪里,并且你不会意外地捕获到你没有尝试的异常捉。
我认为与Python try / catch / else最接近的是使用本地布尔变量来记住是否抛出了异常。
bool success;
try
{
foo();
success = true;
}
catch (MyException)
{
recover();
success = false;
}
if (success)
{
bar();
}
但是如果你这样做,我会问为什么你没有从异常中完全恢复,以便你可以继续,好像已经成功,或者通过返回错误代码甚至只是让他们完全中止异常传播给调用者。
答案 1 :(得分:7)
野蛮的解决方案:创建一个从Exception派生的Else类,在try块的末尾抛出它的一个实例,并使用catch (Else) {...}
来处理其他东西。
我觉得很脏。
答案 2 :(得分:3)
这可能会被投票,但c#没有goto(注意我几乎没有c#知识,所以我不知道这是否有效。)
像
这样的东西try
{
...
}
catch(Exception ex)
{
...
goto Jump_past_tryelse
}
...//Code to execute if the try block DID NOT fail
Jump_past_tryelse:
...
答案 3 :(得分:2)
C#没有这样的概念,所以你只剩下三个选项,
答案 4 :(得分:2)
只需将
try
{
fee();
fi();
foe();
fum();
/// put your "else" stuff here.
/// It will only be executed if fee-fi-foe-fum did not fail.
}
catch(Exception e)
{
// handle exception
}
鉴于此,我没有看到使用try..catch ...... else,除非OP的描述中缺少一些重要的内容。
答案 5 :(得分:2)
请允许我从similar StackOverflow question重复一个想法。您无法直接执行此操作,但您可以编写一个封装所需行为的方法。查看原始问题以了解如何实现该方法(如果您不熟悉lambda表达式和Func
委托)。用法可能如下所示:
TryExceptRaise(() => {
// code that can throw exception
}, (Exception e) => {
// code to run in case of an exception
return (...);
}, () => {
// code to run if there is no exception
return (...);
});
答案 6 :(得分:1)
使用 C#版本7 ,您可以使用本地函数来模拟此行为:
示例1:(自C#版本7起)
void Main()
{
void checkedCode()
{
try
{
foo();
}
catch (Exception ex)
{
recover();
return;
}
// ElseCode here
}
checkedCode();
}
如果您更喜欢 lambda语法,,您还可以声明一个运行方法
void Run(Action r) { r(); }
只需要在代码中存在一次,然后将模式用于匿名方法,如下所示
示例2:(较旧的C#版本和C#版本7)
Run(() => {
try
{
foo();
}
catch (Exception)
{
recover();
return;
}
// ElseCode here
});
您需要在安全的上下文中包含代码。
中试用注意:
return;
在出错时退出。Run
。Run
不一定是本地函数,示例2 也适用于较旧的C#版本答案 7 :(得分:0)
你可以这样做:
if (!IsReadOnly)
{
T newobj = null;
try
{
newobj = DataPortal.Update<T>(this);
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
}
if (newobj != null)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
答案 8 :(得分:0)
这将是像命中
这样的空语句try
{
somethingThatCanThrow();
}
catch(Exception ex)
{
LogException(ex);
return;
}
ContinueFlow();
答案 9 :(得分:0)
if (!IsReadOnly)
{
T newobj;
bool Done;
try
{
newobj = DataPortal.Update<T>(this);
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
Done = true;
}
catch (DataPortalException)
{
// TODO: Implement DataPortal.Update<T>() recovery mechanism
Done = false;
}
finally
{
if (newobj != null && Done == false)
{
List<string> keys = new List<string>(BasicProperties.Keys);
foreach (string key in keys)
{
BasicProperties[key] = newobj.BasicProperties[key];
}
}
}
}