C#:相当于python的try/catch/else块
在Python中,有以下有用的异常处理代码:C#:相当于python的try/catch/else块,c#,python,exception,try-catch,C#,Python,Exception,Try Catch,在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:
# 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
}
}
如果(!IsReadOnly)
{
T newobj;
尝试
{
newobj=DataPortal.Update(这个);
列表键=新列表(BasicProperties.keys);
foreach(字符串键入键)
{
基本属性[键]=新对象基本属性[键];
}
}
捕获(DataPortalException)
{
//TODO:实现DataPortal.Update()恢复机制
}
}
这要求正常代码位于try块中,因为否则,如果引发异常并随后进行处理,newobj
将被取消分配,但是在try块中有这么多与DataPortalException
无关的代码感觉很不自然。怎么办
谢谢您可以这样做:
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];
}
}
}
如果(!IsReadOnly)
{
T newobj=null;
尝试
{
newobj=DataPortal.Update(这个);
}
捕获(DataPortalException)
{
//TODO:实现DataPortal.Update()恢复机制
}
if(newobj!=null)
{
列表键=新列表(BasicProperties.keys);
foreach(字符串键入键)
{
基本属性[键]=新对象基本属性[键];
}
}
}
那将是像hits一样的空语句
try
{
somethingThatCanThrow();
}
catch(Exception ex)
{
LogException(ex);
return;
}
ContinueFlow();
我更希望看到try/catch之外的其余代码,这样就可以清楚地知道您试图捕获的异常来自何处,并且不会意外捕获到您不想捕获的异常 我认为与pythontry/catch/else最接近的等效方法是使用一个局部布尔变量来记住是否引发了异常
bool success;
try
{
foo();
success = true;
}
catch (MyException)
{
recover();
success = false;
}
if (success)
{
bar();
}
但是如果你这样做的话,我会问你为什么不从异常中完全恢复,这样你就可以像成功一样继续,或者通过返回错误代码或者甚至让异常传播到调用方来完全中止。C#没有这样的概念,所以你只有三个选择
- 将else代码放在try中
- 将else代码置于try-catch块之外,使用局部变量指示成功或失败,并在else代码周围使用if块
- 将else代码放在finally块中,使用局部变量表示成功或失败,并在else代码周围使用if块
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的描述中缺少了一些重要的东西。请允许我重复一段文章中的一个想法。您不能直接执行此操作,但可以编写一个封装所需行为的方法。查看原始问题以了解如何实现该方法(如果您不熟悉lambda表达式和
Func
delegate)。用法可能如下所示:
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 (...);
});
野蛮的解决方案:创建一个从Exception派生的Else类,在try块的末尾抛出它的一个实例,并使用
catch(Else){…}
处理其他内容
我觉得自己很脏。这可能会被否决,但c#have goto(注意,我几乎没有c#knowledge,所以我不知道这是否有效) 像这样的怎么样
try
{
...
}
catch(Exception ex)
{
...
goto Jump_past_tryelse
}
...//Code to execute if the try block DID NOT fail
Jump_past_tryelse:
...
如果(!IsReadOnly)
{
T newobj;
布尔多;
尝试
{
newobj=DataPortal.Update(这个);
列表键=新列表(BasicProperties.keys);
foreach(字符串键入键)
{
基本属性[键]=新对象基本属性[键];
}
完成=正确;
}
捕获(DataPortalException)
{
//TODO:实现DataPortal.Update()恢复机制
完成=错误;
}
最后
{
if(newobj!=null&&Done==false)
{
列表键=新列表(BasicProperties.keys);
foreach(字符串键入键)
{
基本属性[键]=新对象基本属性[键];
}
}
}
}
对于C#version 7,您可以使用本地函数来模拟此行为:
示例1:(自C#版本7起)
如果您更喜欢lambda语法,还可以声明run方法
void Run(Action r) { r(); }
它只需要在代码中出现一次,然后对匿名方法使用如下模式
示例2:(较旧的C版本和C版本7)
您需要在安全上下文中包含代码的任何地方
在
注意事项:
- 在这两个示例中,都创建了一个函数上下文,以便我们可以使用
return代码>以在出现错误时退出
- 您可以在JavaScript中找到类似于示例2中使用的模式(例如JQuery使用它们)。因为在C#中不能自调用,所以使用了helper方法
Run
- 由于
不必是本地函数,示例2也适用于较旧的C#版本Run
void Main()
{
void checkedCode()
{
try
{
foo();
}
catch (Exception ex)
{
recover();
return;
}
// ElseCode here
}
checkedCode();
}
void Run(Action r) { r(); }
Run(() => {
try
{
foo();
}
catch (Exception)
{
recover();
return;
}
// ElseCode here
});