You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用集合初始化语法时会调用Dictionary属性的Getter?

为什么第二种初始化方式会抛出NullReferenceException?

这个问题的核心在于你混淆了对象属性赋值和集合初始化器这两种C#语法糖的底层逻辑,咱们一步步拆解:

两种写法的本质区别

第一种(正常运行的写法)

var dataRow = new FlatDataRow { 
    Id = 12, 
    Fields = new Dictionary<string, object>() { { "skills", skills} } 
};

这里你是直接给Fields属性赋值:先创建一个全新的Dictionary<string, object>实例,用集合初始化器给这个新实例添加"skills"键值对,最后把整个实例赋值给Fields属性。整个过程完全不会用到Fields原本的Getter——毕竟你是直接覆盖它的默认null值。

第二种(抛出异常的写法)

var dataRow = new FlatDataRow { 
    Id = 12, 
    Fields = { { "skills", skills} } 
};

这里的{ { "skills", skills} }是集合初始化器语法,它的执行逻辑和赋值完全不同:

  1. 首先调用dataRow.Fields的Getter,试图获取当前Fields的实例(但因为Fields是get;set;属性,默认值是null)
  2. 接着尝试对这个null实例调用Add("skills", skills)方法
  3. 因为实例是null,自然就抛出了NullReferenceException

什么时候第二种写法能正常工作?

集合初始化器语法的前提是:目标集合已经被初始化(不为null)。如果你的FlatDataRow在构造函数里提前初始化了Fields,那第二种写法就没问题:

public class FlatDataRow
{
    public int Id { get; set; }
    public Dictionary<string, object> Fields { get; set; }

    public FlatDataRow()
    {
        // 构造函数里提前初始化集合
        Fields = new Dictionary<string, object>();
    }
}

此时调用dataRow.Fields的Getter会拿到一个有效的Dictionary实例,集合初始化器就能正常调用Add方法添加元素了。

一句话总结

第一种写法是给属性赋值新的集合实例,第二种写法是对已有集合实例添加元素——C#的语法让它们看起来相似,但底层逻辑天差地别,这就是为什么后者会抛出空引用异常。

内容的提问来源于stack exchange,提问作者Ole Albers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:52:17