在所有对象创建、静态方法和构造函数上使用断点进行调试时,我看到了奇怪的控制流

本文关键字:我看 调试 控制流 断点 创建 对象 静态方法 构造函数 | 更新日期: 2023-09-27 18:24:05

这是我的程序:

namespace ConsoleApplication3
{
    public class Program
    {
        public Program():this(20)
        {
            Console.WriteLine("Hi");
        }
        private Program(int i) 
        {
            Console.WriteLine(i.ToString());
        }
        static Program()
        {
            int mess = 50;
            Console.WriteLine("Static");
        }
        Program p = new Program();
        static void Main(string[] args)
        {
            new Program(10);
            Console.ReadLine();
        }
    }
}

我看到,程序的控制命中,

  • 静态构造函数,
  • 然后主方法,
  • 然后是"新程序(10(",
  • 则"程序 p = 新程序((;"
  • 然后"公共程序((:this(20("
  • 然后在最后两件事之间循环。

有以下问题,我声称应该发生:

  1. 它应该在new Program(10)后立即进入private Program(int i),但它没有发生。奇怪。

  2. 我觉得在最后两个调用之间循环背后没有逻辑。如果我必须省略上面的问题 1,并继续盲目地同意其流程是正确的,我认为没有理由在上面序列中提到的最后两个不相关的调用之间以这种方式循环。

没有我能理解的逻辑。

在所有对象创建、静态方法和构造函数上使用断点进行调试时,我看到了奇怪的控制流

首先,静态构造函数几乎可以在 JIT 想要运行它的任何位置运行,只要它发生在创建实例或访问静态字段之前。

至于实例构造函数:

字段初始值设定项在构造函数之前运行;基本上,它变成:

private Program(int i)
{
    // base ctor
    base.ctor();
    // field initializers
    p = new Program();
    // now comes the ctor body
    Console.WriteLine(i.ToString());
}

p = new Program(...)是堆栈溢出。每个new Program(使用任何构造函数(都希望在字段初始值设定项中创建一个new Program()。由于字段初始值设定项发生在构造函数主体之前,因此在堆栈爆炸之前看不到任何Console.WriteLine输出。

相关文章: