一般来说我的理解是类中的静态对象是在第一次引用类时构造的。然而,我遇到了我没有预料到的行为。
考虑下面的课程
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);
}
我能理解为什么会发生这种情况吗?小提琴这里
来自静态构造函数的文档:
静态构造函数用于初始化任何静态数据,或者 执行只需执行一次的特定操作。它 在创建第一个实例或任何实例之前自动调用 静态成员被引用。
让我们详细看看这个。为了使您的代码正常工作,必须在调用
WebColor
之前调用类 WebColor.FromCode("#ffffff")
的静态字段构造函数。
是否已创建
WebColor
的实例?没有。
它的任何静态成员是否被引用?不。
FromCode()
方法不是 WebColor
的成员 - 它是 SmartColor<TColor>
的静态成员,虽然基类的静态方法可以通过派生类调用,但它们实际上并不是该派生类的成员类。
因此,尚未满足调用
WebColor
的静态初始化程序的标准,因此 White
初始化尚未发生,因此尚未将其添加到 _items
中的 SmartColor<T>
。
但请注意,由于调用了
_items
,WebColor.FromCode()
本身已被初始化。