尝试捕获FormatException错误失败。只有Exception能抓住它吗?

时间:2015-07-23 17:47:24

标签: c# debugging exception error-handling

我有一个在运行时接受随机数据的方法(可能是stringint等),然后尝试将此数据添加到随机类型的列表中(例如{{ 1}},List<byte>等)。

由于这种不可预测的特性,我添加了2个错误处理例程。一个用于捕获List<int>错误并执行一些特定操作来修复数据。其次,我还为FormatException添加了一个通用的全部内容,所以如果抛出另一个我没想到的错误,我可以显示详细信息并优雅地退出应用程序。

我遇到的(或者至少对我来说似乎很奇怪)这个奇怪的问题是,每当发出Exception错误时,我的FormatException什么也不做,而错误就是被Catch (FormatException ex)抓住了。因此,应用程序退出而不是能够正确处理错误。

为了帮助隔离这一点,我创建了一个小例子C#WinForms程序来复制问题。

这是主要的表单代码:

Catch (Exception ex)

这是我的2个课程的代码:

private void button1_Click(object sender, EventArgs e)
{
    // This works normally        
    ErrorClass.TestCatchFormatException<string, string>("abc", "def");

    // This also works normally        
    ErrorClass.TestCatchFormatException<int, int>("123", "456");

    // This should raise a FormatException error but only Exception catches it???
    ErrorClass.TestCatchFormatException<int, string>("abc", "456"); 
}

甚至更奇怪的是,当我查看InnerException时,catch-all public class DataClass<T, U> { public T Data1 { get; set; } public U Data2 { get; set; } } public static class ErrorClass { public static void TestCatchFormatException<T, U>(dynamic inputString, dynamic inputString2) where T : IComparable<T> where U : IComparable<U> { try { List<DataClass<T, U>> theList = new List<DataClass<T, U>>(); TypeConverter converter1 = TypeDescriptor.GetConverter(typeof(T)); TypeConverter converter2 = TypeDescriptor.GetConverter(typeof(U)); theList.Add(new DataClass<T, U> { Data1 = converter1.ConvertFrom(inputString.ToString()), Data2 = converter2.ConvertFrom(inputString2.ToString()) }); MessageBox.Show( "Data1 Value is: " + theList[0].Data1.ToString() + "\n" + "Data1 Type is: " + theList[0].Data1.GetType().ToString() + "\n" + "Data2 Value is: " + theList[0].Data2.ToString() + "\n" + "Data2 Type is: " + theList[0].Data2.GetType().ToString()); } catch (FormatException ex) { // Catches nothing for some reason MessageBox.Show("Caught FormatException\n\n" + ex.Message + "\n\n" + ex.InnerException); } catch (Exception ex) { // This catches the error but InnerException says the error is of type FormatException. // Yet FormatException doesn't catch it??? MessageBox.Show("Caught Exception\n\n" + ex.Message + "\n\n" + ex.InnerException); } } } 生成,它说:

  

System.FormatException:输入字符串的格式不正确。

因此它将其检测为Exception错误。但由于某种原因,抓住FormatException什么都不做,只有FormatException可以抓住它。

有谁知道我在这里做错了什么?

2 个答案:

答案 0 :(得分:3)

您的FormatException包含在其他Exception类型中。这就是 .InnerException 属性为FormatException的原因。尝试在看到包装类型的异常时调用 .GetType ,然后抓住它。

答案 1 :(得分:1)

BaseNumberConverter.ConvertFrom()在内部调用辅助函数来抛出异常:

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
     ...
        catch (Exception e) {
            throw FromStringError(text, e);
        }
    }
    return base.ConvertFrom(context, culture, value);
}

FromStringError的实施是:

internal virtual Exception FromStringError(string failedText, Exception innerException) {
        return new Exception(SR.GetString(SR.ConvertInvalidPrimitive, failedText, TargetType.Name), innerException);
}

因此它会抛出Exception包裹实际的FormatException并添加一些其他信息(即它尝试转换的值以及它尝试转换为的类型)。为什么它不会抛出另一个我不知道的FormatException

在C#6之前,无法创建基于catch捕获的InnerException。您必须抓住Exception并检查InnerException类型以便以不同方式处理它。

使用C#6,您可以使用异常过滤器:

catch (Exception ex) when (ex.InnerExcpetion is FormatException)
{
    // Catches nothing for some reason               
    MessageBox.Show("Caught FormatException\n\n" + ex.Message + "\n\n" + ex.InnerException);
}

catch (Exception ex)
{
    // This catches the error but InnerException says the error is of type FormatException.  
    // Yet FormatException doesn't catch it???
    MessageBox.Show("Caught Exception\n\n" + ex.Message + "\n\n" + ex.InnerException);
}