您可以从TypeInitializationException中恢复吗?

时间:2019-10-19 21:41:59

标签: c# static-initialization static-initializer

这只是为了好玩。

类型初始化器又称为静态构造器,即使它们抛出并且Static Constructors (C# Programming Guide)明确表示也被调用一次。

  

如果静态构造函数引发异常,则运行时不会再次调用该异常,并且该类型将在程序运行所在的应用程序域的生存期内保持未初始化状态。

这可以通过以下代码轻松演示。

public static int i = 0;
public static async Task Main()
{
    try { new X(); } catch (TypeInitializationException e) { Console.WriteLine(e.GetBaseException().Message); }

    i = 10;
    try { new X(); } catch (TypeInitializationException e) { Console.WriteLine(e.GetBaseException().Message); }
}

public class X
{
    static X() { if( Program.i < 10 ) throw new Exception($"i too small: {i}"); }
}

输出为

i too small: 0
i too small: 0

问:是否有办法从中恢复并使第二个new X()工作?只是为了好玩。


为什么我认为有办法?

(C# Programming Guide)状态:

  
      
  • 静态构造函数不能直接调用,只能由公共语言运行库(CLR)调用。它会自动调用。

  •   
  • 用户无法控制何时在程序中执行静态构造函数。

  •   

C# 6.0 draft specification状态:

  

静态构造函数不能继承,也不能直接调用。

但是RuntimeHelpers.RunClassConstructor存在:

System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(X).TypeHandle);

我知道多次运行静态构造函数与在需要的时间调用静态构造函数有很大不同,但是嘿,这只是为了好玩。


仅单个AppDomain

我正在寻求一个AppDomain解决方案。不是这个:

public class StaticCtorClock
{
    public static async Task Main(string[] args)
    {
        while (true)
        {
            try { AppDomain.CreateDomain("").CreateInstance(typeof(X).Assembly.FullName, typeof(X).FullName); }
            catch ( Exception e ) { } 
            await Task.Delay(TimeSpan.FromMilliseconds(100));
        }
    }

    public class X
    {
        static X()
        {
            Console.Write($"\r{DateTime.Now.ToString("o")}");
            throw new Exception("Bad.");
        }
    }
}

0 个答案:

没有答案
相关问题