System.TypeInitializationException 类

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

当类初始值设定项无法初始化类型时,将创建 a TypeInitializationException 并传递对该类型的类初始值设定项引发的异常的引用。 InnerExceptionTypeInitializationException 属性保存着基础异常。

通常, TypeInitializationException 异常反映灾难性条件(运行时无法实例化类型),以防止应用程序继续。 通常情况下,TypeInitializationException 是在应用程序执行环境发生某些变化时引发的。 因此,除了可能用于对调试代码进行故障排除之外,不应在块中 try/catch 处理异常。 相反,应调查并消除异常的原因。

TypeInitializationException 使用具有值0x80131534的 HRESULT COR_E_TYPEINITIALIZATION

有关实例 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 类包含一个字段:在 C# 中是 static,在 Visual Basic 中是 Shared,其字段类型为 TestClass,并通过向类构造函数传递值 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 文件或包含序列化数据的文件)但无法找到,则也可能引发异常。

正则表达式匹配超时值

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

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

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: {rgx.ToString()}");
        Console.WriteLine($"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()
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 。 以下日历类构造函数可以引发此异常:

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