为何C#中定义在不同程序集的struct未初始化使用编译结果不同
问题原因
C#编译器对结构类型的明确赋值检查规则,会根据结构是否定义在当前编译的程序集内发生差异:
- 当
MetaWorkspace定义在当前程序集时
你声明的public string Name { get; set; }这类自动实现属性,编译器会为其生成私有的隐藏后备字段。此时编译器能看到结构的所有实例字段(包括私有后备字段),根据明确赋值规则,你必须要么调用结构的构造函数完成初始化,要么给所有实例字段逐一赋值,才能访问结构的实例成员(包括属性的setter)。
你代码里只声明了MetaWorkspace ws;没有调用构造函数,也没法访问私有后备字段直接赋值,所以当你尝试调用ws.Id的setter时,编译器判定ws未完成明确赋值,抛出CS0165错误。 - 当
MetaWorkspace定义在外部引用的程序集时
编译器无法访问外部程序集里结构的私有成员,也就看不到自动属性对应的私有后备字段。此时编译器判定结构明确赋值的标准,仅检查你是否给所有可访问的实例字段完成了赋值。如果结构没有公开的实例字段(你的例子里只有公开属性,没有公开字段),编译器会默认该结构只要完成声明就算已明确赋值,所以你可以直接调用属性的setter,代码正常编译。
行为合法性说明
这种写法不属于未定义行为:
C#运行时会保证所有值类型的实例都完成零初始化,哪怕你没有显式调用构造函数,局部结构变量在栈上分配时也会被默认清零,所有字段都处于默认值状态(引用类型字段为null,值类型字段为对应零值)。你后续给Id赋值的操作是完全合法的,最终得到的是符合结构定义的正常对象。
内容的提问来源于stack exchange,提问作者ghd
相关产品推荐
相关产品推荐

