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

由于这种不可预测的性质,我添加了2个错误处理例程。捕获FormatException错误并执行一些特定操作来修复数据的方法。其次,我还为Exception添加了一个通用包,因此,如果引发了我不期望的另一个错误,我可以显示详细信息并正常退出应用程序。

我遇到的奇怪问题(或者至少对我来说似乎很奇怪)是,每当抛出FormatException错误时,我的Catch (FormatException ex)都不执行任何操作,而是由Catch (Exception ex)捕获该错误。因此,该应用程序无法正常处理错误,而是退出。

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

这是主要的表单代码:

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");
}

这是我的两个类的代码:
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);
        }
    }
}

甚至更奇怪的是,当我查看InnerException时,生成了所有Exception,它说:



因此它将其检测为FormatException错误。但是由于某种原因,捕获FormatException不会执行任何操作,只有Exception可以捕获它。

有人知道我在做什么错吗?

最佳答案

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并添加了一些其他信息(即,它试图转换的值和它试图转换的类型)。为什么它不抛出另一个我不知道的catch

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

使用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);
}

09-13 13:13