静态对象构造顺序

问题描述 投票:0回答:1

一般来说我的理解是类中的静态对象是在第一次引用类时构造的。然而,我遇到了我没有预料到的行为。

考虑下面的课程

public abstract class SmartColor<TColor> where TColor : SmartColor<TColor> {
    private static readonly ConcurrentDictionary<string, TColor> _items = new();

    protected SmartColor(string code, string name) {
        Code = code;
        Name = name;
        //register all colors
        foreach (var field in typeof(TColor).GetFields(BindingFlags.Public | BindingFlags.Static)) {
            TColor? item = (TColor?)field.GetValue(null);
            if (item is not null) {
                Register(item);
            }
        }
    }

    public string Code { get; }

    public string Name { get; }

    public static TColor FromCode(string code) {
        if (_items.TryGetValue(code, out var result)) {
            return result;
        }
        return null;
    }

    private void Register(TColor item) {
        _items.GetOrAdd(item.Code, item);
    }
}

又继承自这个

public class WebColor : SmartColor<WebColor> {
    public static readonly WebColor White = new WebColor("#ffffff", nameof(White));
    public static readonly WebColor Black = new WebColor("#000000", nameof(Black));

    protected WebColor(string code, string name) : base(code, name) {
    }
}

如果像这样使用它会产生 NullReferenceException

public static void Main()
{
    WebColor color = WebColor.FromCode("#ffffff");
    Console.WriteLine(color.Name);
}

我能理解为什么会发生这种情况吗?小提琴这里

c# static c#-12.0
1个回答
1
投票

来自静态构造函数的文档

静态构造函数用于初始化任何静态数据,或者 执行只需执行一次的特定操作。它 在创建第一个实例或任何实例之前自动调用 静态成员被引用。

让我们详细看看这个。为了使您的代码正常工作,必须在调用

WebColor
之前调用类
WebColor.FromCode("#ffffff")
的静态字段构造函数。

是否已创建

WebColor
的实例?没有。

它的任何静态成员是否被引用?不。

FromCode()
方法不是
WebColor
的成员 - 它是
SmartColor<TColor>
的静态成员,虽然基类的静态方法可以通过派生类调用,但它们实际上并不是该派生类的成员类。

因此,尚未满足调用

WebColor
的静态初始化程序的标准,因此
White
初始化尚未发生,因此尚未将其添加到
_items
中的
SmartColor<T>

但请注意,由于调用了

_items
WebColor.FromCode()
本身已被初始化。

© www.soinside.com 2019 - 2024. All rights reserved.