System.TypeInitializationException 类

本文提供了此 API 参考文档的补充说明。

当类初始值设定项初始化类型失败时,将创建一个 TypeInitializationException,并向其传递对由该类型的类初始值设定项引发的异常的引用。 TypeInitializationExceptionInnerException 属性保存着基础异常。

通常,TypeInitializationException 异常反映阻止应用程序继续继续运行的灾难性条件(运行时无法实例化类型)。 最常见的是,TypeInitializationException 是由应用程序执行环境中的一些更改引发的。 因此,除了可能用于排查调试代码故障之外,不应在 try/catch 块中处理异常。 相反,应调查并消除异常的根源。

TypeInitializationException 使用的 HRESULT COR_E_TYPEINITIALIZATION 具有值 0x80131534。

有关实例的初始属性值的列表TypeInitializationException,请参阅TypeInitializationException构造函数。

以下部分介绍引发 TypeInitializationException 异常的一些情况。

静态构造函数

如果存在静态构造函数,运行时会在创建类型的新实例之前自动调用该构造函数。 静态构造函数可由开发人员显式定义。 如果未显式定义静态构造函数,编译器会自动创建一个来初始化类型的任何 static(在 C# 或 F# 中)或 Shared(在 Visual Basic 中)成员。 有关静态构造函数的详细信息,请参阅静态构造函数

通常,当静态构造函数无法实例化类型时,将引发 TypeInitializationException 异常。 InnerException 属性指示静态构造函数无法实例化类型的原因。 TypeInitializationException 异常的一些更常见的原因包括:

  • 静态构造函数中未经处理的异常

    如果静态构造函数中引发了异常,该异常将包装在 TypeInitializationException 异常中,并且该类型无法实例化。

    静态构造函数并不总是在源代码中显式定义,这往往使得此异常难以排除故障。 静态构造函数在以下情况存在于类型中:

    • 它已显式定义为类型的成员。

    • 该类型具有 static(在 C# 或 F# 中)或 Shared(在 Visual Basic 中)变量,这些变量在单个语句中声明并初始化。 在这种情况下,语言编译器为类型生成静态构造函数。 可以使用 IL 反汇编程序等实用工具对其进行检查。 例如,当 C# 和 VB 编译器编译以下示例时,它们将为静态构造函数生成与下面类似的 IL:

    .method private specialname rtspecialname static
             void  .cctor() cil managed
    {
       // Code size       12 (0xc)
       .maxstack  8
       IL_0000:  ldc.i4.3
       IL_0001:  newobj     instance void TestClass::.ctor(int32)
       IL_0006:  stsfld     class TestClass Example::test
       IL_000b:  ret
    } // end of method Example::.cctor
    

    以下示例演示编译器生成的静态构造函数引发的 TypeInitializationException 异常。 Example 类包含一个 TestClass 类型的 static(在 C# 中)或 Shared(在 Visual Basic)字段,该字段通过将值 3 传递给其类构造函数来实例化。 然而,该值是非法的;仅允许 0 或 1 的值。 因此,TestClass 类构造函数将引发 ArgumentOutOfRangeException。 由于未处理此异常,它被包装在 TypeInitializationException 异常中。

    using System;
    
    public class Example
    {
       private static TestClass test = new TestClass(3);
       
       public static void Main()
       {
          Example ex = new Example();
          Console.WriteLine(test.Value);
       }
    }
    
    public class TestClass
    {
       public readonly int Value;
       
       public TestClass(int value)
       {
          if (value < 0 || value > 1) throw new ArgumentOutOfRangeException(nameof(value));
          Value = value;
       }
    }
    // The example displays the following output:
    //    Unhandled Exception: System.TypeInitializationException: 
    //       The type initializer for 'Example' threw an exception. ---> 
    //       System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
    //       at TestClass..ctor(Int32 value)
    //       at Example..cctor()
    //       --- End of inner exception stack trace ---
    //       at Example.Main()
    
    Public Class Example1
        Shared test As New TestClass(3)
    
        Public Shared Sub Main()
            Dim ex As New Example1()
            Console.WriteLine(test.Value)
        End Sub
    End Class
    
    Public Class TestClass
       Public ReadOnly Value As Integer
       
       Public Sub New(value As Integer)
            If value < 0 Or value > 1 Then Throw New ArgumentOutOfRangeException(NameOf(value))
            value = value
       End Sub
    End Class
    ' The example displays the following output:
    '    Unhandled Exception: System.TypeInitializationException: 
    '       The type initializer for 'Example' threw an exception. ---> 
    '       System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
    '       at TestClass..ctor(Int32 value)
    '       at Example..cctor()
    '       --- End of inner exception stack trace ---
    '       at Example.Main()
    

    请注意,异常消息显示有关 InnerException 属性的信息。

  • 缺少的程序集或数据文件

    TypeInitializationException 异常的常见原因是应用程序开发和测试环境中存在的程序集或数据文件在其运行时环境中缺失。 例如,可以使用下面的命令行语法将以下示例编译为名为 Missing1a.dll 的程序集:

    csc -t:library Missing1a.cs
    
    fsc --target:library Missing1a.fs
    
    vbc Missing1a.vb -t:library
    
    using System;
    
    public class InfoModule
    {
       private DateTime firstUse;
       private int ctr = 0;
    
       public InfoModule(DateTime dat)
       {
          firstUse = dat;
       }
       
       public int Increment()
       {
          return ++ctr;
       }
       
       public DateTime GetInitializationTime()
       {
          return firstUse;
       }
    }
    
    open System
    
    type InfoModule(firstUse: DateTime) =
        let mutable ctr = 0
    
        member _.Increment() =
            ctr <- ctr + 1
            ctr
       
        member _.GetInitializationTime() =
            firstUse
    
    Public Class InfoModule
       Private firstUse As DateTime
       Private ctr As Integer = 0
    
       Public Sub New(dat As DateTime)
          firstUse = dat
       End Sub
       
       Public Function Increment() As Integer
          ctr += 1
          Return ctr
       End Function
       
       Public Function GetInitializationTime() As DateTime
          Return firstUse
       End Function
    End Class
    

    然后,可以通过包含对 Missing1a.dll 的引用,将以下示例编译为名为 Missing1.exe 的可执行文件:

    csc Missing1.cs /r:Missing1a.dll
    
    vbc Missing1.vb /r:Missing1a.dll
    

    但是,如果重命名、移动或删除 Missing1a.dll 并运行该示例,则会引发 TypeInitializationException 异常并显示示例所示的输出。 请注意,异常消息包含有关 InnerException 属性的信息。 在这种情况下,内部异常是运行时找不到依赖程序集而引发的 FileNotFoundException

    using System;
    
    public class MissingEx1
    {
        public static void Main()
        {
            Person p = new Person("John", "Doe");
            Console.WriteLine(p);
        }
    }
    
    public class Person
    {
        static readonly InfoModule s_infoModule;
    
        readonly string _fName;
        readonly string _lName;
    
        static Person()
        {
            s_infoModule = new InfoModule(DateTime.UtcNow);
        }
    
        public Person(string fName, string lName)
        {
            _fName = fName;
            _lName = lName;
            s_infoModule.Increment();
        }
    
        public override string ToString()
        {
            return string.Format("{0} {1}", _fName, _lName);
        }
    }
    // The example displays the following output if missing1a.dll is renamed or removed:
    //    Unhandled Exception: System.TypeInitializationException: 
    //       The type initializer for 'Person' threw an exception. ---> 
    //       System.IO.FileNotFoundException: Could not load file or assembly 
    //       'Missing1a, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' 
    //       or one of its dependencies. The system cannot find the file specified.
    //       at Person..cctor()
    //       --- End of inner exception stack trace ---
    //       at Person..ctor(String fName, String lName)
    //       at Example.Main()
    
    open System
    
    type Person(fName, lName) =
        static let infoModule = InfoModule DateTime.UtcNow
        
        do infoModule.Increment() |> ignore
       
        override _.ToString() =
            $"{fName} {lName}"
    let p = Person("John", "Doe")
    
    printfn $"{p}"
    // The example displays the following output if missing1a.dll is renamed or removed:
    //    Unhandled Exception: System.TypeInitializationException: 
    //       The type initializer for 'Person' threw an exception. ---> 
    //       System.IO.FileNotFoundException: Could not load file or assembly 
    //       'Missing1a, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' 
    //       or one of its dependencies. The system cannot find the file specified.
    //       at Person..cctor()
    //       --- End of inner exception stack trace ---
    //       at Person..ctor(String fName, String lName)
    //       at Example.Main()
    
    Module Example3
        Public Sub Main()
            Dim p As New Person("John", "Doe")
            Console.WriteLine(p)
        End Sub
    End Module
    
    Public Class Person
       Shared infoModule As InfoModule
       
       Dim fName As String
       Dim mName As String
       Dim lName As String
       
       Shared Sub New()
          infoModule = New InfoModule(DateTime.UtcNow)
       End Sub
       
       Public Sub New(fName As String, lName As String)
          Me.fName = fName
          Me.lName = lName
          infoModule.Increment()
       End Sub
       
       Public Overrides Function ToString() As String
          Return String.Format("{0} {1}", fName, lName)
       End Function
    End Class
    ' The example displays the following output if missing1a.dll is renamed or removed:
    '    Unhandled Exception: System.TypeInitializationException: 
    '       The type initializer for 'Person' threw an exception. ---> 
    '       System.IO.FileNotFoundException: Could not load file or assembly 
    '       'Missing1a, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' 
    '       or one of its dependencies. The system cannot find the file specified.
    '       at Person..cctor()
    '       --- End of inner exception stack trace ---
    '       at Person..ctor(String fName, String lName)
    '       at Example.Main()
    

    注意

    在此示例中,由于无法加载程序集,因此引发了 TypeInitializationException 异常。 如果静态构造函数尝试打开一个查找不到的数据文件(例如的配置文件、XML 文件或包含序列化数据的文件),则也可能引发该异常。

正则表达式匹配超时值

可以为每个应用程序域设置正则表达式模式匹配操作的默认超时值。 超时是通过为 AppDomain.SetData 方法指定“REGEX_DEFAULT_MATCH_TIMEOUT”属性的 TimeSpan 值来定义的。 时间间隔必须是大于零且小于约 24 天的有效 TimeSpan 对象。 如果未满足这些要求,则尝试设置默认超时值会引发一个 ArgumentOutOfRangeException,而后者又包装在 TypeInitializationException 异常中。

以下示例显示分配给“REGEX_DEFAULT_MATCH_TIMEOUT”属性的值无效时引发的 TypeInitializationException 值。 若要消除异常,请将“REGEX_DEFAULT_MATCH_TIMEOUT”属性设置为大于零且小于约 24 天的 TimeSpan 值。

using System;
using System.Text.RegularExpressions;

public class RegexEx1
{
    public static void Main()
    {
        AppDomain domain = AppDomain.CurrentDomain;
        // Set a timeout interval of -2 seconds.
        domain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromSeconds(-2));

        Regex rgx = new Regex("[aeiouy]");
        Console.WriteLine("Regular expression pattern: {0}", rgx.ToString());
        Console.WriteLine("Timeout interval for this regex: {0} seconds",
                          rgx.MatchTimeout.TotalSeconds);
    }
}
// The example displays the following output:
//    Unhandled Exception: System.TypeInitializationException: 
//       The type initializer for 'System.Text.RegularExpressions.Regex' threw an exception. ---> 
//       System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
//       Parameter name: AppDomain data 'REGEX_DEFAULT_MATCH_TIMEOUT' contains an invalid value or 
//       object for specifying a default matching timeout for System.Text.RegularExpressions.Regex.
//       at System.Text.RegularExpressions.Regex.InitDefaultMatchTimeout()
//       at System.Text.RegularExpressions.Regex..cctor()
//       --- End of inner exception stack trace ---
//       at System.Text.RegularExpressions.Regex..ctor(String pattern)
//       at Example.Main()
open System
open System.Text.RegularExpressions

let domain = AppDomain.CurrentDomain
// Set a timeout interval of -2 seconds.
domain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromSeconds -2)

let rgx = Regex "[aeiouy]"
printfn $"Regular expression pattern: {rgx}"
printfn $"Timeout interval for this regex: {rgx.MatchTimeout.TotalSeconds} seconds"
// The example displays the following output:
//    Unhandled Exception: System.TypeInitializationException: 
//       The type initializer for 'System.Text.RegularExpressions.Regex' threw an exception. ---> 
//       System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
//       Parameter name: AppDomain data 'REGEX_DEFAULT_MATCH_TIMEOUT' contains an invalid value or 
//       object for specifying a default matching timeout for System.Text.RegularExpressions.Regex.
//       at System.Text.RegularExpressions.Regex.InitDefaultMatchTimeout()
//       at System.Text.RegularExpressions.Regex..cctor()
//       --- End of inner exception stack trace ---
//       at System.Text.RegularExpressions.Regex..ctor(String pattern)
//       at Example.Main()
Imports System.Text.RegularExpressions

Module Example4
    Public Sub Main()
        Dim domain As AppDomain = AppDomain.CurrentDomain
        ' Set a timeout interval of -2 seconds.
        domain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromSeconds(-2))

        Dim rgx As New Regex("[aeiouy]")
        Console.WriteLine("Regular expression pattern: {0}", rgx.ToString())
        Console.WriteLine("Timeout interval for this regex: {0} seconds",
                        rgx.MatchTimeout.TotalSeconds)
    End Sub
End Module
' The example displays the following output:
'    Unhandled Exception: System.TypeInitializationException: 
'       The type initializer for 'System.Text.RegularExpressions.Regex' threw an exception. ---> 
'       System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
'       Parameter name: AppDomain data 'REGEX_DEFAULT_MATCH_TIMEOUT' contains an invalid value or 
'       object for specifying a default matching timeout for System.Text.RegularExpressions.Regex.
'       at System.Text.RegularExpressions.Regex.InitDefaultMatchTimeout()
'       at System.Text.RegularExpressions.Regex..cctor()
'       --- End of inner exception stack trace ---
'       at System.Text.RegularExpressions.Regex..ctor(String pattern)
'       at Example.Main()

日历和区域性数据

如果尝试实例化日历,但运行时无法实例化对应于该日历的 CultureInfo 对象,则会引发 TypeInitializationException 异常。 以下日历类构造函数可能引发此异常:

由于这些区域性的文化数据应该在所有系统上都可用,因此很少会遇到此异常。