简体   繁体   English

如何从嵌套的try-catch块中重新抛出先前的异常? (C#)

[英]How to rethrow a prior exception from inside a nested try-catch block? (C#)

I have code that attempts a type conversion. 我有尝试类型转换的代码。 If it fails, I want to try something else, and if that also fails, then rethrow the original exception attempted by the first conversion. 如果失败,我想尝试别的东西,如果失败,则重新抛出第一次转换尝试的原始异常。 The problem is that the only way I know of to rethrow is to have ' throw; 问题是,我知道重新抛出的唯一方法就是“ throw; ' sitting at the end of the catch block. '坐在拦截区的尽头。 What happens when I only want the rethrow to happen from within another catch block? 当我只希望从另一个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; }
}

As you can see above, I have to use ' throw e; 如上所示,我必须使用' throw e; ', which resets the call stack. ',它会重置调用堆栈。

Only workaround I've though of so far is (imo) gross: 到目前为止我唯一的解决方法是(imo)粗略:

bool handled = true;
... 
catch { handled = false; }
if( !handled ) throw;

There is no way to rethrow an exception from an outer catch block inside an inner catch block. 没有办法重新抛出从外异常catch的内部块inner catch块。 The best way to achieve this pattern is to note whether or not the inner operation succeeded 实现此模式的最佳方法是注意内部操作是否成功

catch (InvalidCastException e) {
  bool threw = false;
  try {
    ...
  } catch { 
    threw = true;
  }
  if (threw) {
    throw;
  }
}

If you are intending to make multiple attempts at conversion then it certainly makes sense to use non-throwing operations where applicable so that you sidestep the problem entirely. 如果您打算多次尝试转换,那么在适用的情况下使用非投掷操作肯定是有意义的,这样您就可以完全回避问题。

Supposing that's not possible for the sake of argument, the next step is to question the throw e; 假设为了争论而不可能,下一步是质疑throw e; approach. 做法。 In the example code you give, IMHO there is no problem at all if your throw resets the call stack. 在您提供的示例代码中,如果您的throw重置调用堆栈,则IMHO根本没有问题。 Once someone gets to the source code for this method (which the modified call stack would still point to), I think it's pretty obvious what's going on. 一旦有人获得此方法的源代码(修改后的调用堆栈仍将指向该方法),我认为很明显发生了什么。 So while resetting the call stack is always a questionable decision, in this particular case it should be allowed to happen because there would be no tangible drawback. 因此,重置调用堆栈总是一个值得怀疑的决定, 在这种特殊情况下应该允许它发生,因为没有明显的缺点。

Finally, the workaround you mention is interesting as well as gross (agree on that!). 最后,你提到的解决方法既有趣又有意义(同意!)。

I tried the following and it seems to achieve your goal, when the 2nd exception occurs (in this case, the ArgumentException ) it throws the first exception ( InvalidCastException ) 我尝试了以下内容,它似乎达到了你的目标,当第二个异常发生时(在这种情况下, ArgumentException )它抛出第一个异常( 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;
}

Hope this helps, 希望这可以帮助,

Alan. 艾伦。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM