静态对象构造顺序疑问:调用WebColor.FromCode为何触发空引用异常?
问题:静态对象构造时机导致的NullReferenceException
我原本认为类的静态对象会在类首次被引用时构造,但遇到了不符合预期的行为。现有如下抽象泛型类、子类及调用代码,运行时会抛出NullReferenceException,请分析原因。
抽象泛型类代码
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) { } }
调用代码
public static void Main() { WebColor color = WebColor.FromCode("#ffffff"); Console.WriteLine(color.Name); }
异常原因分析
核心触发原因:静态初始化时机不匹配
调用WebColor.FromCode("#ffffff")时,本质是调用基类泛型封闭类型SmartColor<WebColor>的静态方法,CLR只会初始化SmartColor<WebColor>的静态成员(即_items字典),不会触发子类WebColor的静态字段(White、Black)的初始化。此时_items字典为空,FromCode返回null,后续访问color.Name自然抛出NullReferenceException。
额外逻辑缺陷(即使触发子类初始化仍存在问题)
假设通过访问WebColor.White等方式触发了子类静态初始化,原代码的基类构造函数逻辑仍有漏洞:
- 静态字段按代码顺序初始化,当构造第一个实例(
White)时,基类构造函数反射遍历子类静态字段,此时White字段尚未完成赋值(对象构造完成后才会给字段赋值),Black字段也未开始初始化,两者都为null,因此没有任何实例被注册到_items。 - 当构造第二个实例(
Black)时,基类构造函数反射遍历字段,此时White已完成初始化会被注册,但Black字段仍处于构造中、值为null,无法被注册,最终_items中只有White,缺少Black。
验证示例
若在FromCode前先触发子类静态初始化,异常即可避免:
public static void Main() { // 访问子类静态字段,触发WebColor的静态初始化 var _ = WebColor.White; WebColor color = WebColor.FromCode("#ffffff"); Console.WriteLine(color.Name); // 输出White }
内容的提问来源于stack exchange,提问作者user23137927
相关产品推荐
相关产品推荐

