类型初始化器(静态构造函数)异常处理

11
我正在使用C#编写WCF服务。最初,我的实现中有一个静态构造函数来进行一次性的初始化,但其中一些被执行的初始化可能(暂时)失败了。
似乎静态构造函数只会被调用一次,即使第一次(失败的)尝试抛出异常?任何后续实例化我的类的尝试都将立即失败,并且代码实际上不会被执行,而会抛出一个“TypeInitializationException”异常。
C#语言规范规定,静态构造函数最多只会被调用一次,但如果有异常,基本上这是一个您永远无法恢复的错误?我漏掉了什么吗?我想应该将任何具有风险的内容移动到服务的实例构造函数中,并手动检查类初始化是否已经成功完成。
3个回答

4
所以你可以将关键部分包装在try/catch中,至少这意味着类型不会初始化失败,但是如果初始化代码如此关键,那么这种行为实际上是好的——该类型在未初始化状态下不可用。
另一个选择是将其作为单例处理——每次尝试获取实例时,您都可以正确地创建该类型,直到成功为止,即使第一次失败也是如此。
您仍需要对调用者进行一些错误处理,以防Instance第一(或第二等)次返回null。
编辑:如果不想要单例,则只需让实例构造函数初始化静态部分。
例如:
private object _lock = new object()
private bool _initialized;

public T()
{
   lock(_lock)
   {
      if(!_initialized)
      {
         try
         {
           //Do static stuff here
         }
         catch(Exception ex_)
         {
           //Handle exception
         }
      } 
   }
}

1
这实际上就是我现在拥有的,除了我使用了一些双重检查锁定,并且我的 _initialized 布尔值是 volatile 的(如果没有双重检查锁定,这应该是不必要的)。 - Thorarin

4
这里的教训很简单:不要在静态构造函数中进行可能失败的操作。

MSDN提到该类型将保持未初始化状态,但我并没有立即意识到这意味着永远不可能创建实例。我本来期望会有更明确的警告。虽然绕过它并不是什么大问题,但这确实使得静态构造函数变得不那么有用了:( - Thorarin
@Thorarin - 仅限于应用程序域的生命周期。根据MSDN http://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx中的描述,该类型将在您的程序所运行的应用程序域的生命周期内保持未初始化状态。 - VoodooChild

1
我过去使用的解决方法是创建一个单例。只有在失败意味着整个应用程序无法运行时,才使静态构造函数失败。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接