C#字段与表达式体属性字符串拼接执行差异原因解析
导致运行结果差异的核心原因
两种写法的本质、执行时机完全不同,直接造成了输出不一致。
1. 两种语法的本质区别
- 用
=定义的是静态字段:是类级别的数据存储位置,属于类的固有状态,会在类型首次被访问时完成一次性初始化,值会被存在对应的内存位置中,后续除非手动修改否则不会变化。 - 用
=>定义的是表达式体只读属性:本质是属性get访问器的语法简写,完整等价于public static string PropertyX { get { return 表达式; } },没有专属的后备存储字段,不会在类加载阶段提前计算值。
2. 执行逻辑的具体差异
静态字段(=写法)的执行逻辑
静态字段的初始化表达式仅在类静态初始化阶段执行1次,执行顺序严格按照字段在代码中从上到下的声明顺序推进。
在给出的字段赋值示例中:
- 首次访问
DummyClass.Property1时触发类静态初始化 - 按照声明顺序先初始化
Property1,此时排在后面的Property2还未执行赋值,处于string类型的默认值null - C#中字符串与
null拼接时,null会被自动视为空字符串,因此Property1初始化后的值为"STRING_PART_1\"(描述中提到的输出漏了末尾的反斜杠属于笔误,实际运行时会带这个反斜杠,只是缺失了Property2对应的后半段内容) - 后续初始化
Property2为"STRING_PART_2"时,已经完成赋值的Property1不会被重新计算,因此最终输出只有前半段。
补充验证:如果把两个静态字段的声明顺序调换,先写
Property2的赋值再写Property1的赋值,初始化Property1时Property2已经完成赋值,输出结果就会和表达式体属性版本完全一致。
表达式体属性(=>写法)的执行逻辑
表达式体属性=>后的逻辑,每次被访问时都会实时执行计算,不存在提前初始化的步骤。
在给出的表达式体属性示例中:
- 首次访问
DummyClass.Property1时触发类静态初始化,由于类中没有定义静态字段、也没有自定义静态构造函数,初始化阶段无额外操作 - 执行
Property1的get逻辑,计算拼接表达式时需要读取Property2的值 - 触发
Property2的get逻辑,直接返回常量值"STRING_PART_2" - 拼接完成得到完整的
"STRING_PART_1\STRING_PART_2"返回,因此输出符合预期。
内容的提问来源于stack exchange,提问作者Arthur Attout
相关产品推荐
相关产品推荐

