如何从嵌套的try-catch块中重新抛出先前的exception? (C#)
我有尝试类型转换的代码。 如果失败,我想尝试别的东西,如果失败,则重新抛出第一次转换尝试的原始exception。 问题是,我知道重新抛出的唯一方法就是“ throw;
‘坐在拦截区的尽头。 当我只希望从另一个catch块中发生重新抛出时会发生什么?
try { valueFromData = Convert.ChangeType(valueFromData, pi.PropertyType); } catch(InvalidCastException e) { Debug.WriteLine(String.Concat("Info - Direct conversion failed. Attempting to convert using String as an intermidiate type.")); try { valueFromData = Convert.ChangeType(valueFromData.ToString(), pi.PropertyType); } catch { throw e; } }
如上所示,我必须使用’ throw e;
‘,它会重置调用堆栈。
到目前为止我唯一的解决方法是(imo)粗略:
bool handled = true; ... catch { handled = false; } if( !handled ) throw;
无法从内部catch
块内的外部catch
块重新抛出exception。 实现此模式的最佳方法是注意内部操作是否成功
catch (InvalidCastException e) { bool threw = false; try { ... } catch { threw = true; } if (threw) { throw; } }
如果您打算多次尝试转换,那么在适用的情况下使用非投掷操作肯定是有意义的,这样您就可以完全回避问题。
假设为了论证而不可能,下一步是质疑throw e;
做法。 在你提供的示例代码中,如果你的throw
重置了调用堆栈,恕我直言就没有任何问题。 一旦有人获得此方法的源代码(修改后的调用堆栈仍将指向该代码),我认为很明显发生了什么。 因此,重置调用堆栈总是一个值得怀疑的决定, 在这种特殊情况下应该允许它发生,因为没有明显的缺点。
最后,你提到的解决方法既有趣又有意义(同意!)。
我尝试了以下内容,它似乎达到了你的目标,当第二个exception发生时(在这种情况下, ArgumentException )它抛出第一个exception( InvalidCastException )
[TestMethod] [ExpectedException(typeof(InvalidCastException))] public void ReThrowException() { var ret = false; try { ret = F1(1); } catch (InvalidCastException ex) { try { ret = F1(2); } catch (Exception e) { Debug.WriteLine(e.Message); throw ex; } } } private bool F1(int i) { if (i == 1) { throw new InvalidCastException(); } else { throw new ArgumentException(); } return false; }
希望这可以帮助,
艾伦。