c# – 当我访问它时,为什么我的初始化静态属性为null?

我有以下代码(从实际代码提取)

public static class AssemblyLogger {

    public static Lazy<Window> Window { get; } = new Lazy<Window>(NewWindowHandler);

    public static IScheduler Scheduler =>
        new dispatcherScheduler( Window.Value.dispatcher );

}

当我调用Scheduler时,我得到一个NullReferenceException.我看到调试器停止了

enter image description here

据我所知,这应该是不可能的.窗口是静态初始化和只读的,因此任何对它的进一步访问应该只是get,它永远不应该为null.

我已经设置了一个针对初始化器的断点,但它永远不会被击中

enter image description here

我也尝试过静态只读字段,但仍然存在同样的问题

public static readonly Lazy<Window> Window  = new Lazy<Window>(NewWindowHandler);

是否可能对静态初始化有竞争条件?

到目前为止尝试制作MCVE并不成功.以下规范测试我的最小可用代码和真实代码. MCVE通过:(而真正的一个失败.我错过了一些背景,需要进一步的工作来隔离问题.

public class Tester
{
    public static class AssemblyLoggerMCVE
    {

        public static Lazy<Window> Window { get; } = new Lazy<Window>(NewWindowHandler);

        private static Window NewWindowHandler() => new Window();

        public static IScheduler Scheduler =>
            new dispatcherScheduler(Window.Value.dispatcher);

    }

    /// This passes
    [StaFact]
    public void AssemblyLoggerMCVEShouldWork()
    {
        AssemblyLoggerMCVE.Scheduler.Should().NotBeNull();

    }

    /// This fails
    [StaFact]
    public void AssemblyLoggerShouldWork()
    {
        AssemblyLogger.Scheduler.Should().NotBeNull();

    }
}

解决方法

错误可以通过以下测试用例清楚地复制,该测试用例具有比所建议的问题更多的上下文.

public class Tester
{
    public class AssemblyLoggerControlModel
    {
        public static IScheduler S = AssemblyLoggerMCVE.Scheduler;
    }

    public class AssemblyLogger
    {

        public static AssemblyLoggerControlModel ModelInstance { get; } = 
            new AssemblyLoggerControlModel();

        public static readonly Lazy<Window> Window =
            new Lazy<Window>(NewWindowHandler);

        private static Window NewWindowHandler() => new Window();

        public static IScheduler Scheduler => 
            new dispatcherScheduler(Window.Value.dispatcher);

    }


}

静态初始化器之间存在循环依赖关系.静态属性的静态初始化AssemblyLogger.ModelInstance导致静态属性AssemblyLoggerControlModel.S被初始化,然后尝试调用静态AssemblyLogger.Scheduler方法,该方法又试图访问Window,因为AssemblyLogger的静态初始化未完成仍为空.

基本上我的代码是纯粹的邪恶,最好的办法是

enter image description here

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...