我有尝试进行类型转换的代码。如果失败,我想尝试别的东西,如果失败,则重新抛出第一次转换尝试的原始异常。问题是,我知道重新抛出的唯一方法是让“throw;
”位于catch块的末尾。当我只希望从另一个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;
”,resets调用堆栈。
到目前为止,我唯一的解决方法是(imo)粗略:
bool handled = true;
...
catch { handled = false; }
if( !handled ) throw;
答案 0 :(得分:7)
无法从catch
catch块中的外部inner
块重新抛出异常。实现此模式的最佳方法是注意内部操作是否成功
catch (InvalidCastException e) {
bool threw = false;
try {
...
} catch {
threw = true;
}
if (threw) {
throw;
}
}
答案 1 :(得分:1)
如果您打算多次尝试转换,那么在适用的情况下使用非投掷操作肯定是有意义的,这样您就可以完全回避问题。
假设为了论证而不可能,下一步是质疑throw e;
方法。在您给出的示例代码中,如果您的throw
重置调用堆栈,则IMHO根本没有问题。一旦有人获得此方法的源代码(修改后的调用堆栈仍将指向该方法),我认为很明显发生了什么。因此,重置调用堆栈总是一个值得怀疑的决定,在这种特殊情况下应该允许它发生,因为没有明显的缺点。
最后,你提到的解决方法既有趣也有意义(同意这一点!)。
答案 2 :(得分:1)
我尝试了以下内容,它似乎达到了你的目标,当第二个异常发生时(在这种情况下, 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;
}
希望这有帮助,
艾伦。