在C#中更改结构的大小是一个重大改变吗?

时间:2016-06-16 17:19:09

标签: c# .net memory struct cil

好奇的是,在C#中改变struct / value类型的大小是一个重大改变?结构在内存布局方面往往更敏感,因为更改它们会直接影响数组/其他结构的大小。在使用的库中的结构布局发生变化之后,是否存在任何代码断开的示例(二进制或源代码)?

注意:通过“休息”,我的意思是它根本无法编译或IL无效。例如,我不认为这是一个重大改变:

eclipse-wtp

因为它仍在运行。

2 个答案:

答案 0 :(得分:8)

通过添加字段来改变大小对于严格管理的代码是可以的。

添加字段是不间断的更改,因为代码将使用新类型重新进行JIT编辑,并且所有分配都将使用正确的大小。由于它是值类型,因此无论如何都会使用空值正确初始化新字段。

删除/更改现有字段或属性的类型肯定会发生变化。

值类型是密封的 - 因此没有其他库可以从该类型派生 - 所以与类不同,它们不会产生"这个派生类没有实现新的虚拟属性/接口方法"

注意:如果值类型用于互操作或控制之外的任何其他类型的二进制序列化,则任何更改都会中断。

即。其他人使用MyLib.Point {int x;int y;}将带有二进制序列化的点列表保存到文件中。如果现在" MyLib"向MyLib.Point添加一个新字段,而不再使用二进制序列化读取序列化数据。与本地互操作相似的问题。

答案 1 :(得分:3)

是的,如果添加新字段,即使在严格管理的代码中,也绝对可以使用源代码不兼容。以您的示例为例,这将编译版本1而不是版本2:

MyStruct s;
Console.WriteLine(s);

原因是如果为所有字段分配了值,C#允许使用struct local。在版本1中,没有字段,因此s是"明确分配"。但是,如果在版本2中添加了一个字段,即使它是私有的,那么这也不再编译,因为s不再是明确分配的。

这种情况应该是二进制兼容的,因为CLR保证将字段初始化为默认值。

Jared Parsons对结构中私人字段的主题有一个good blog post,其中详细说明了更改私有实现细节会导致危险(对于不安全的代码)或破坏的其他情况。