Classe System.TypeInitializationException
Este artigo fornece observações complementares à documentação de referência para essa API.
Quando um inicializador da classe não inicializa um tipo, uma TypeInitializationException é criada e é passada uma referência à exceção gerada pelo inicializador da classe do tipo. A propriedade InnerException de TypeInitializationException contém a exceção subjacente.
Normalmente, a exceção TypeInitializationException reflete uma condição catastrófica (o runtime não consegue instanciar um tipo) que impede que um aplicativo continue. Geralmente, o TypeInitializationException é lançado em resposta a alguma alteração no ambiente de execução do aplicativo. Consequentemente, a não ser possivelmente para solucionar problemas de código de depuração, a exceção não deve ser tratada em um bloco try
/catch
. Em vez disso, a causa da exceção deve ser investigada e eliminada.
TypeInitializationException usa o HRESULT COR_E_TYPEINITIALIZATION
, que tem o valor 0x80131534.
Para obter uma lista de valores de propriedade inicial para uma instância do TypeInitializationException, consulte o TypeInitializationException construtores.
As seções a seguir descrevem algumas das situações em que uma exceção TypeInitializationException é lançada.
Construtores estáticos
Um construtor estático, se existir, é chamado automaticamente pelo runtime antes de criar uma nova instância de um tipo. Os construtores estáticos podem ser explicitamente definidos por um desenvolvedor. Se um construtor estático não estiver explicitamente definido, os compiladores criarão automaticamente um para inicializar qualquer membro do tipo static
(em C# ou F#) ou Shared
(no Visual Basic). Para obter mais informações sobre construtores estáticos, consulte Construtores Estáticos.
Geralmente, uma exceção TypeInitializationException é lançada quando um construtor estático não consegue instanciar um tipo. A propriedade InnerException indica por que o construtor estático não pôde instanciar o tipo. Algumas das causas mais comuns de uma exceção TypeInitializationException são:
Uma exceção sem tratamento em um construtor estático
Se uma exceção for lançada em um construtor estático, essa exceção será encapsulada em uma exceção TypeInitializationException e o tipo não poderá ser instanciado.
O que geralmente dificulta a solução dessa exceção é o fato de que os construtores estáticos nem sempre são definidos explicitamente no código-fonte. Um construtor estático existe em um tipo se:
Ele foi explicitamente definido como um membro de um tipo.
O tipo tem
static
(em C# ou F#) ouShared
(no Visual Basic) variáveis que são declaradas e inicializadas em um único comando. Nesse caso, o compilador de linguagem gera um construtor estático para o tipo. Você pode inspecioná-lo usando um utilitário como IL Disassembler. Por exemplo, quando os compiladores C# e VB compilam o exemplo a seguir, eles geram a IL para um construtor estático semelhante a este:
.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
O exemplo a seguir mostra uma exceção TypeInitializationException lançada por um construtor estático gerado pelo compilador. A classe
Example
inclui um campostatic
(em C#) ouShared
(no Visual Basic) do tipoTestClass
que é instanciado passando-se um valor de 3 para seu construtor de classe. Esse valor, entretanto, é ilegal; somente valores de 0 ou 1 são permitidos. Como resultado, o construtor da classeTestClass
lança um ArgumentOutOfRangeException. Como essa exceção não é identificada, ela é envolvida em uma exceção 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()
Observe que a mensagem de exceção exibe informações sobre a propriedade InnerException.
Falta um assembly ou um arquivo de dados
Uma causa comum de uma exceção TypeInitializationException é a ausência de um assembly ou arquivo de dados presente nos ambientes de desenvolvimento e teste de um aplicativo em seu ambiente de runtime. Por exemplo, você pode compilar o exemplo a seguir para um assembly chamado Missing1a.dll usando esta sintaxe de linha de comando:
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
Em seguida, você pode compilar o exemplo a seguir em um executável chamado Missing1.exe, incluindo uma referência a Missing1a.dll:
csc Missing1.cs /r:Missing1a.dll
vbc Missing1.vb /r:Missing1a.dll
No entanto, se você renomear, mover ou excluir o Missing1a.dll e executar o exemplo, ele lançará uma exceção TypeInitializationException e exibirá a saída mostrada no exemplo. Observe que a mensagem de exceção inclui informações sobre a propriedade InnerException. Nesse caso, a exceção interna é uma FileNotFoundException que é lançada porque o runtime não consegue encontrar o assembly dependente.
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()
Observação
Neste exemplo, uma exceção TypeInitializationException foi lançada porque um assembly não pôde ser carregado. A exceção também pode ser lançada se um construtor estático tentar abrir um arquivo de dados, como um arquivo de configuração, um arquivo XML ou um arquivo contendo dados serializados, que não possa ser encontrado.
Valores de tempo limite para correspondência de expressão regular
Você pode definir o valor de tempo limite padrão para uma operação de padrões correspondentes de expressão regular por domínio de aplicativo. O tempo limite é definido por uma especificação de um valor TimeSpan para a propriedade "REGEX_DEFAULT_MATCH_TIMEOUT" para o método AppDomain.SetData. O intervalo de tempo deve ser um objeto TimeSpan válido que seja maior que zero e menor que aproximadamente 24 dias. Se esses requisitos não forem atendidos, a tentativa de definir o valor de tempo limite padrão lança uma exceção ArgumentOutOfRangeException, que, por sua vez, é encapsulada em uma exceção TypeInitializationException.
O exemplo a seguir mostra a TypeInitializationException que é lançada quando o valor atribuído à propriedade "REGEX_DEFAULT_MATCH_TIMEOUT" for inválido. Para eliminar a exceção, defina a propriedade "REGEX_DEFAULT_MATCH_TIMEOUT" como um valor TimeSpan maior que zero e menor que aproximadamente 24 dias.
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()
Calendários e dados culturais
Se você tentar instanciar um calendário, mas o runtime não conseguir instanciar o objeto CultureInfo que corresponde a esse calendário, ele lançará uma exceção TypeInitializationException. Essa exceção pode ser lançada pelos seguintes construtores de classe de calendário:
- O construtor sem parâmetros da classe JapaneseCalendar.
- O construtor sem parâmetros da classe KoreanCalendar.
- O construtor sem parâmetros da classe TaiwanCalendar.
Como os dados culturais para essas culturas devem estar disponíveis em todos os sistemas, você raramente, ou nunca, encontrará essa exceção.