TypeLoadException隐藏内部异常

时间:2010-10-05 03:40:05

标签: c# windows-mobile exception-handling compact-framework error-handling

我正在使用Compact Framework 3.5 / VS2008。我在使用TypeLoadException时遇到了奇怪的行为。以下代码抛出此错误。原因是数据库连接存在问题。但是由于某些未知原因,此内部异常将丢失,并且不包含在TypeLoadException中。

try
{
    settingsFromDb = SettingsFromDbManager.Instance;
}
catch (Exception ex)
{
    throw ex; // BREAKPOINT HERE
}

如果我们查看下面的SettingsFromDbManager类,可以看出它是一个简单的单例类。 Load()方法中发生数据库错误。我没有在示例中包含此代码。如果我在下面的示例中指示的位置放置一个断点,我可以看到数据库错误。不幸的是,如果我在上面的代码中指出的位置放置一个断点,那么我得到的只是TypeLoadException而没有内部异常。没有任何迹象表明发生了数据库问题。这很糟糕:(有谁知道为什么会发生这种奇怪的行为?

干杯
标记

public sealed class SettingsFromDbManager
{
    static readonly SettingsFromDbManager _instance = new SettingsFromDbManager(); 

    SettingsFromDbManager()
    {
        try
        {
            Load();
        }
        catch (Exception ex)
        {
            throw ex; // BREAKPOINT HERE
        }
    }

    public static SettingsFromDbManager Instance
    {
        get
        {
            return _instance;
        }
    }

    .... more code ...
}

**更新**

非常感谢所有伟大的建议和帮助!

皮埃尔我用了你亲切写的测试课。这是我用它调用的代码。它一定是Compact Framework的一个怪癖我想是因为当我检查异常时它是TypeLoadException而没有内部异常:(

try
{
    Fail.Test();
}
catch (Exception ex)
{
    var x = ex.ToString(); // BREAKPOINT HERE
}

我认为VinayC可能是正确的。这有点超出我的知识。不知道现在该怎么办。我不想放弃我的Singleton类 - 它们很有用。我正在使用http://csharpindepth.com/Articles/General/Singleton.aspx中的“第四版”Singleton模式。我以前没有使用它们,但似乎是一个好主意,在应用程序周围共享一些实用程序类的相同实例,而不是多次创建和处理它们。 Compact Framework是一个大问题。

*更新*

WOO HOO!我所要做的就是更改Singleton类,如下所示。它在属性getter中实例化类。现在,我的例外情况如预期一样浮出水面:)

public sealed class SettingsFromDbManager
{
    static SettingsFromDbManager _instance = null; 

    SettingsFromDbManager()
    {
        try
        {
            Load();
        }
        catch (Exception ex)
        {
            throw new Exception("Error loading settings", ex); 
        }
    }

    public static SettingsFromDbManager Instance
    {
        get
        {
            if (_instance == null)
                _instance = new SettingsFromDbManager();

            return _instance;
        }
    }

    .... more code ...
}

2 个答案:

答案 0 :(得分:2)

据我所知,静态构造函数可以在不同的线程上运行(或者更具体地说,在不同的调用链上运行) - 它是运行时的保证,它们将在访问类型之前被调用。静态构造函数中的异常会将类型标记为不适用于app域。当访问类型时,您将获得一个TypeInitializationException(根据文档),但类型构造函数中发生的异常不会作为内部异常,因为它不在同一个调用链上 - 因此静态构造函数可能已经在之前执行过。正如汉斯指出的那样,这里唯一的问题是TypeLoadException而不是TypeIntializationException。

编辑:这是解释类型初始值设定项的延迟/急切语义的article。您的代码可以是急切的实现(即,即使在第一次访问类型字段之前,也可能会调用静态构造函数)

答案 1 :(得分:1)

没有充分理由说明静态构造函数中引发的异常不会显示在原始调用位置中。但是,我不明白为什么你没有得到System.TypeInitializationException,这应该是你的静态构造函数失败时抛出的异常。

以下是一段示例代码,它抛出System.TypeInitializationException并将内部异常设置为"failed"异常:

class Fail
{
    static Fail()
    {
    }

    Fail()
    {
        throw new System.Exception ("failed");
    }

    static readonly Fail instance = new Fail ();

    public static void Test()
    {
    }
}

我会进一步调查,以了解为什么会收到TypeLoadException,而无法正确加载或初始化程序集(TypeLoadException Class在MSDN中)时会出现这种情况。